ibm5250 0.1.0.dev11__tar.gz → 0.1.0.dev13__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: ibm5250
3
- Version: 0.1.0.dev11
3
+ Version: 0.1.0.dev13
4
4
  Summary: IBM 5250 terminal automation library
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.11
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ibm5250"
3
- version = "0.1.0.dev11"
3
+ version = "0.1.0.dev13"
4
4
  description = "IBM 5250 terminal automation library"
5
5
  requires-python = ">=3.11"
6
6
 
@@ -180,6 +180,10 @@ class TN5250Connection:
180
180
  Attempt TN5250E enhanced negotiation before falling back to basic.
181
181
  timeout:
182
182
  Socket timeout in seconds.
183
+ terminal_type:
184
+ Telnet terminal type reported to IBM i, which selects the display
185
+ device model. The default ``IBM-3477-FC`` is a 27×132 colour display;
186
+ monochrome types such as ``IBM-3477-FG`` make the host drop colours.
183
187
  """
184
188
 
185
189
  def __init__(
@@ -192,6 +196,7 @@ class TN5250Connection:
192
196
  device_name: str = "PYTERM01",
193
197
  use_tn5250e: bool = True,
194
198
  timeout: float = 30.0,
199
+ terminal_type: str = "IBM-3477-FC",
195
200
  ) -> None:
196
201
  self.host = host
197
202
  self.port = port
@@ -211,7 +216,7 @@ class TN5250Connection:
211
216
  self._eor_sent = False
212
217
  self._eor_rcvd = False
213
218
  self._ttype_will_sent = False
214
- self._negotiated_ttype = "IBM-3477-FG" # screen model reported to IBM i
219
+ self._negotiated_ttype = terminal_type.upper() # screen model reported to IBM i
215
220
 
216
221
  # Byte 9 (opcode/var-header length) of the last received TN5250E record.
217
222
  # Used to detect header-only Cancel-Invite records (opcode 0x0A).
@@ -457,6 +462,11 @@ class TN5250Connection:
457
462
  def connected(self) -> bool:
458
463
  return self._sock is not None
459
464
 
465
+ @property
466
+ def terminal_type(self) -> str:
467
+ """Telnet terminal type reported to the host (e.g. ``IBM-3477-FC``)."""
468
+ return self._negotiated_ttype
469
+
460
470
  @property
461
471
  def tn5250e_active(self) -> bool:
462
472
  """True if TN5250E enhanced mode was successfully negotiated."""
@@ -217,6 +217,11 @@ class DataStreamParser:
217
217
  yield from self._clear_unit(sub_command)
218
218
  # A clear is usually followed by further commands (typically
219
219
  # ESC + WTD) in the same record, so keep parsing.
220
+ elif sub_command == Command.CLEAR_FORMAT_TABLE:
221
+ # ESC 0x50 has no operands; a WTD usually follows in the
222
+ # same record, so keep parsing.
223
+ byte_offset += 1
224
+ yield DSEvent(type=DSEventType.COMMAND, command=sub_command)
220
225
  elif sub_command == Command.WRITE_STRUCTURED_FIELD:
221
226
  # ESC 0xF3 — Write Structured Field
222
227
  byte_offset += 1
@@ -507,6 +512,9 @@ class DataStreamParser:
507
512
  yield DSEvent(type=DSEventType.COMMAND, command=next_byte)
508
513
  yield from self._clear_unit(next_byte)
509
514
  current_buffer_position = 0
515
+ elif next_byte == Command.CLEAR_FORMAT_TABLE:
516
+ byte_offset += 2 # ESC + command; no operands
517
+ yield DSEvent(type=DSEventType.COMMAND, command=next_byte)
510
518
  # ESC + WTD (0x04 0x11): embedded Write to Display sub-command
511
519
  elif next_byte == Command.WRITE_TO_DISPLAY:
512
520
  if byte_offset + 4 > total_bytes:
@@ -722,6 +722,13 @@ class Screen:
722
722
  if 0 <= event.position < self._size:
723
723
  self._chars[event.position] = event.attribute_value or EBCDIC_NULL
724
724
  self._attrs[event.position] = event.attribute_value
725
+ # Like a real workstation, end an input field with a normal attribute so
726
+ # its display attribute (e.g. underline) stops at the end of the field
727
+ # instead of running on to the next attribute byte on the screen.
728
+ if event.field_format_word and event.field_length:
729
+ end_pos = (event.position + 1 + event.field_length) % self._size
730
+ self._chars[end_pos] = Attr.NORMAL
731
+ self._attrs[end_pos] = Attr.NORMAL
725
732
 
726
733
  def _recalc_field_lengths(self) -> None:
727
734
  """Compute each field's length based on its successor's start_pos."""
@@ -676,8 +676,10 @@ class Terminal:
676
676
 
677
677
  def _send_query_reply(self) -> None:
678
678
  """Respond to a server WSF Query with our terminal capabilities."""
679
- log.debug("Sending Query Reply (IBM-3179-2, 24x80 colour)")
680
- payload = build_query_reply(device_type="3477", device_model="FG")
679
+ # Report the same device as the Telnet terminal type, e.g. IBM-3477-FC.
680
+ _, device_type, device_model = f"{self._conn.terminal_type}--".split("-")[:3]
681
+ log.debug("Sending Query Reply (%s-%s)", device_type, device_model)
682
+ payload = build_query_reply(device_type=device_type, device_model=device_model)
681
683
  self._conn.send_record(payload, data_type=TN5250EDataType.INPUT, aid=0x88)
682
684
 
683
685
  def _wait_for(
@@ -13,7 +13,7 @@ wheels = [
13
13
 
14
14
  [[package]]
15
15
  name = "ibm5250"
16
- version = "0.1.0.dev11"
16
+ version = "0.1.0.dev13"
17
17
  source = { editable = "." }
18
18
 
19
19
  [package.dev-dependencies]
File without changes
File without changes
File without changes