jetstream-api 0.15.0__tar.gz → 0.16.0__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.
Files changed (27) hide show
  1. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/PKG-INFO +27 -1
  2. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/README.md +26 -0
  3. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/__init__.py +1 -1
  4. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/admin.py +2 -2
  5. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/properties.py +137 -29
  6. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/jetstream_api.egg-info/PKG-INFO +27 -1
  7. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/pyproject.toml +1 -1
  8. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/LICENSE.txt +0 -0
  9. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/_codec.py +0 -0
  10. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/admintopic.py +0 -0
  11. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/common.py +0 -0
  12. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/connectivity.py +0 -0
  13. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/exception.py +0 -0
  14. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/msg.py +0 -0
  15. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/partitioner.py +0 -0
  16. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/pattern.py +0 -0
  17. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/producer.py +0 -0
  18. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/py.typed +0 -0
  19. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/qmgr.py +0 -0
  20. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/topic.py +0 -0
  21. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/ilink/util.py +0 -0
  22. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/jetstream_api.egg-info/SOURCES.txt +0 -0
  23. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/jetstream_api.egg-info/dependency_links.txt +0 -0
  24. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/jetstream_api.egg-info/requires.txt +0 -0
  25. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/jetstream_api.egg-info/top_level.txt +0 -0
  26. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/setup.cfg +0 -0
  27. {jetstream_api-0.15.0 → jetstream_api-0.16.0}/tests/test_example.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jetstream-api
3
- Version: 0.15.0
3
+ Version: 0.16.0
4
4
  Summary: Python client API for iLink M.O.M. (Message Oriented Middleware)
5
5
  Author: snowjeans
6
6
  License: Boost Software License - Version 1.0 - August 17th, 2003
@@ -60,6 +60,32 @@ lz4 배치 압축을 쓰려면 `pip install "jetstream-api[lz4]"`, zstd 배치
60
60
  ## 설치 방법
61
61
  pip install jetstream-api
62
62
 
63
+ ## 0.16.0 변경 - 세그먼트 이름을 토픽과 같은 형식으로, 오타 대입 거부 (자바 v2.12.0 과 같음)
64
+
65
+ - **이름 규칙이 정해졌습니다 - 개수는 맨 복수형, 목록은 `...List` 접미.** 토픽이 `partitions` 를 쓰는 형식 그대로입니다.
66
+ 0.15.0 이 하루 쓴 이름 둘을 여기로 옮깁니다.
67
+
68
+ | 자리 | 0.15.0 | **0.16.0** |
69
+ |---|---|---|
70
+ | 세그먼트 **개수** (`ILQueueProperty`) | `numberOfSegment` | **`segments`** |
71
+ | 세그먼트 **목록** (`ILQueueRealTimeInfo`) | `segments` | **`segmentInfoList`** |
72
+
73
+ - ★ **0.15.0 의 두 이름은 남기지 않고 지웠습니다.** 남기면 개수에 이름이 셋이 되고, 더 나쁘게는 `segments` 가
74
+ 클래스마다 다른 뜻(개수 vs 목록)이 됩니다. 0.15.0 은 하루짜리였고, 아래 가드 덕분에 **지운 것이 조용하지 않습니다.**
75
+ - **`numberOfPartition` 과 `partitions` 는 그대로 있습니다.** 예전부터 쓰던 이름이라 영구 별칭으로 남습니다.
76
+ - 큐에 진짜 분산 파티션이 생기면 그 수는 **토픽과 같은 이름(`partitions`)** 으로 따로 들어옵니다. 지금 있는 이름을
77
+ 그쪽으로 돌리지 않습니다 - **재사용은 제거보다 나쁩니다.** 제거는 그 자리에서 터지지만 재사용은 조용히 다른 값을 줍니다.
78
+ - **속성 객체가 모르는 필드 이름 대입을 거부합니다.** 지금까지는 `prop.numberOfSegmnet = 4` 같은 오타가 **예외도 없이**
79
+ 쓰레기 속성을 만들고 실제 값은 그대로였습니다 - 읽기는 원래 `AttributeError` 였는데 **쓰기만 침묵**해서 옛 값이 그대로
80
+ 서버로 나갔습니다.
81
+ - 이름이 바뀐 필드는 **무엇으로 바뀌었는지까지** 알려 줍니다:
82
+ `AttributeError: ILQueueProperty has no attribute numberOfSegment - 0.16.0 에서 segments 로 바뀌었다`
83
+ - 정말 임의 속성을 얹어야 하면 `object.__setattr__(obj, name, value)` 로 우회할 수 있습니다. 그 값은 **와이어에 실리지
84
+ 않습니다.**
85
+ - 생성자가 도는 동안은 열려 있습니다(필드를 만들어야 하므로). 상속해 쓰는 응용도 `super().__init__()` 뒤에 자기 필드를
86
+ 만들 수 있습니다.
87
+ - **와이어는 달라지지 않습니다.** 0.15.0 과 바이트가 같습니다(큐 속성 2200 · 구엔진 4096 · 실시간정보). 이 판도 엔진 판을 가리지 않습니다.
88
+
63
89
  ## 0.15.0 변경 - 큐의 "파티션" 이 "세그먼트" 가 됩니다 (자바 v2.11.0 과 같음)
64
90
 
65
91
  - **`ILQueueProperty.numberOfPartition` 이 `numberOfSegment` 로 바뀝니다.** 값도 자리도 그대로이고 **이름만** 바뀝니다.
@@ -10,6 +10,32 @@ lz4 배치 압축을 쓰려면 `pip install "jetstream-api[lz4]"`, zstd 배치
10
10
  ## 설치 방법
11
11
  pip install jetstream-api
12
12
 
13
+ ## 0.16.0 변경 - 세그먼트 이름을 토픽과 같은 형식으로, 오타 대입 거부 (자바 v2.12.0 과 같음)
14
+
15
+ - **이름 규칙이 정해졌습니다 - 개수는 맨 복수형, 목록은 `...List` 접미.** 토픽이 `partitions` 를 쓰는 형식 그대로입니다.
16
+ 0.15.0 이 하루 쓴 이름 둘을 여기로 옮깁니다.
17
+
18
+ | 자리 | 0.15.0 | **0.16.0** |
19
+ |---|---|---|
20
+ | 세그먼트 **개수** (`ILQueueProperty`) | `numberOfSegment` | **`segments`** |
21
+ | 세그먼트 **목록** (`ILQueueRealTimeInfo`) | `segments` | **`segmentInfoList`** |
22
+
23
+ - ★ **0.15.0 의 두 이름은 남기지 않고 지웠습니다.** 남기면 개수에 이름이 셋이 되고, 더 나쁘게는 `segments` 가
24
+ 클래스마다 다른 뜻(개수 vs 목록)이 됩니다. 0.15.0 은 하루짜리였고, 아래 가드 덕분에 **지운 것이 조용하지 않습니다.**
25
+ - **`numberOfPartition` 과 `partitions` 는 그대로 있습니다.** 예전부터 쓰던 이름이라 영구 별칭으로 남습니다.
26
+ - 큐에 진짜 분산 파티션이 생기면 그 수는 **토픽과 같은 이름(`partitions`)** 으로 따로 들어옵니다. 지금 있는 이름을
27
+ 그쪽으로 돌리지 않습니다 - **재사용은 제거보다 나쁩니다.** 제거는 그 자리에서 터지지만 재사용은 조용히 다른 값을 줍니다.
28
+ - **속성 객체가 모르는 필드 이름 대입을 거부합니다.** 지금까지는 `prop.numberOfSegmnet = 4` 같은 오타가 **예외도 없이**
29
+ 쓰레기 속성을 만들고 실제 값은 그대로였습니다 - 읽기는 원래 `AttributeError` 였는데 **쓰기만 침묵**해서 옛 값이 그대로
30
+ 서버로 나갔습니다.
31
+ - 이름이 바뀐 필드는 **무엇으로 바뀌었는지까지** 알려 줍니다:
32
+ `AttributeError: ILQueueProperty has no attribute numberOfSegment - 0.16.0 에서 segments 로 바뀌었다`
33
+ - 정말 임의 속성을 얹어야 하면 `object.__setattr__(obj, name, value)` 로 우회할 수 있습니다. 그 값은 **와이어에 실리지
34
+ 않습니다.**
35
+ - 생성자가 도는 동안은 열려 있습니다(필드를 만들어야 하므로). 상속해 쓰는 응용도 `super().__init__()` 뒤에 자기 필드를
36
+ 만들 수 있습니다.
37
+ - **와이어는 달라지지 않습니다.** 0.15.0 과 바이트가 같습니다(큐 속성 2200 · 구엔진 4096 · 실시간정보). 이 판도 엔진 판을 가리지 않습니다.
38
+
13
39
  ## 0.15.0 변경 - 큐의 "파티션" 이 "세그먼트" 가 됩니다 (자바 v2.11.0 과 같음)
14
40
 
15
41
  - **`ILQueueProperty.numberOfPartition` 이 `numberOfSegment` 로 바뀝니다.** 값도 자리도 그대로이고 **이름만** 바뀝니다.
@@ -1,6 +1,6 @@
1
1
  """iLink - Python client API for iLink M.O.M. (Message Oriented Middleware)."""
2
2
 
3
- __version__ = "0.15.0"
3
+ __version__ = "0.16.0"
4
4
 
5
5
  # --- Admin / Service ---
6
6
  from .admin import ILAdminService, ILAdminQmgr, ILLogBrowser, ILQueueBrowser
@@ -5523,7 +5523,7 @@ class ILAdminQmgr:
5523
5523
  Returns:
5524
5524
  ILQueueRealTimeInfo: 현재 깊이, 미커밋 put/get 건수, 열려 있는
5525
5525
  클라이언트/채널 수, 마지막 put/get 을 한 클라이언트와 시각,
5526
- 세그먼트별 상세(``getSegments()``).
5526
+ 세그먼트별 상세(``getSegmentInfoList()``).
5527
5527
 
5528
5528
  Raises:
5529
5529
  ILOperationException: 그런 큐가 없을 때.
@@ -5538,7 +5538,7 @@ class ILAdminQmgr:
5538
5538
  그 시절 엔진은 이 요청에 **큐 속성 블롭을 통째로** 답한다. 사용 현황
5539
5539
  통계가 속성 안에 들어 있었기 때문이다. 클라이언트가 알아서 판별해
5540
5540
  같은 필드를 채우므로 호출부는 달라질 게 없다. 다만
5541
- :attr:`~ilink.properties.ILQueueRealTimeInfo.segments` 는 **빈
5541
+ :attr:`~ilink.properties.ILQueueRealTimeInfo.segmentInfoList` 는 **빈
5542
5542
  목록**이다 - 저장 칸 나누기는 6.3.3 에서 들어온 기능이라 구엔진 큐에는
5543
5543
  세그먼트라는 개념 자체가 없다.
5544
5544
  """
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import datetime
4
+ import functools
4
5
  from enum import IntEnum
5
6
  from typing import List
6
7
 
@@ -94,6 +95,75 @@ class _AutoAccessor:
94
95
  **세터를 쓴다.**
95
96
  """
96
97
 
98
+ #: 이 인스턴스의 필드 생성이 끝났는지. 생성자가 도는 동안은 False 다.
99
+ _il_sealed = False
100
+ #: 생성자 중첩 깊이. 하위 클래스가 ``super().__init__()`` 을 부를 때를 센다.
101
+ _il_init_depth = 0
102
+ #: 이름이 바뀐 필드. ``{옛 이름: (새 이름, 바뀐 판)}``. 오타 거부 문구에 실어
103
+ #: **무엇으로 바뀌었는지**까지 알려 준다 - 거부만 하면 부르는 쪽이 헤맨다.
104
+ _RENAMED: dict = {}
105
+
106
+ def __init_subclass__(cls, **kwargs) -> None:
107
+ """하위 클래스의 ``__init__`` 을 감싸 **끝나는 순간 봉인**한다.
108
+
109
+ Note:
110
+ 봉인 뒤에는 :meth:`__setattr__` 이 모르는 이름을 거부한다. 생성자가
111
+ 도는 동안은 필드를 만들어야 하므로 열어 둔다. ``super().__init__()``
112
+ 을 부르는 하위 클래스가 있으므로 **깊이를 세어 제일 바깥 생성자가
113
+ 끝날 때** 봉인한다 - 안쪽에서 봉인하면 하위 클래스가 자기 필드를
114
+ 만들지 못한다.
115
+ """
116
+ super().__init_subclass__(**kwargs)
117
+ init = cls.__dict__.get("__init__")
118
+ if init is None:
119
+ return
120
+
121
+ @functools.wraps(init)
122
+ def _wrapped(self, *args, **kw):
123
+ object.__setattr__(self, "_il_init_depth", self._il_init_depth + 1)
124
+ try:
125
+ init(self, *args, **kw)
126
+ finally:
127
+ depth = self._il_init_depth - 1
128
+ object.__setattr__(self, "_il_init_depth", depth)
129
+ if depth == 0:
130
+ object.__setattr__(self, "_il_sealed", True)
131
+
132
+ cls.__init__ = _wrapped
133
+
134
+ def __setattr__(self, name: str, value) -> None:
135
+ """**모르는 필드 이름 대입을 거부한다.**
136
+
137
+ Args:
138
+ name (str): 필드 이름.
139
+ value: 넣을 값.
140
+
141
+ Raises:
142
+ AttributeError: 그런 필드가 없을 때.
143
+
144
+ Note:
145
+ 전에는 오타가 **조용했다** - ``prop.numberOfSegmnet = 4`` 가 예외도
146
+ 없이 쓰레기 속성을 만들고 실제 값은 그대로였다. 읽기는 원래
147
+ ``AttributeError`` 였는데 **쓰기만 침묵해서** 와이어에 옛 값이 나갔다.
148
+
149
+ 정말 임의 속성을 얹어야 하면 ``object.__setattr__(obj, name, value)``
150
+ 로 우회할 수 있다. 그때는 **와이어에 실리지 않는다**는 것을 부르는
151
+ 쪽이 안다는 뜻이다.
152
+ """
153
+ if not self._il_sealed or name in self.__dict__ or hasattr(type(self), name):
154
+ object.__setattr__(self, name, value)
155
+ return
156
+ moved = type(self)._RENAMED.get(name)
157
+ if moved is not None:
158
+ raise AttributeError(
159
+ f"{self.__class__.__name__} has no attribute {name}"
160
+ f" - {moved[1]} 에서 {moved[0]} 로 바뀌었다"
161
+ )
162
+ raise AttributeError(
163
+ f"{self.__class__.__name__} has no attribute {name}"
164
+ f" - 필드 이름을 확인하라 (임의 속성을 얹으려면 object.__setattr__ 을 쓴다)"
165
+ )
166
+
97
167
  def __getattr__(self, name: str):
98
168
  """없는 속성 접근을 필드 기반 접근자로 해석한다.
99
169
 
@@ -428,6 +498,7 @@ class SegmentItem(_AutoAccessor):
428
498
 
429
499
  #: :class:`SegmentItem` 의 **옛 이름**. 같은 클래스 객체라 ``isinstance`` 도 통한다.
430
500
  #: 엔진 7.x(SVN 3448)에서 큐의 "파티션" 이 "세그먼트" 로 바뀌기 전 이름이다.
501
+ #: **영구히 세그먼트를 가리킨다** - 다른 뜻으로 재사용하지 않는다.
431
502
  PartitionItem = SegmentItem
432
503
 
433
504
 
@@ -649,21 +720,27 @@ class ILQueueProperty(_AutoAccessor):
649
720
  스펙: 기본 10485760 · 범위 0~9223372036854775807 · 단위 byte · 변경 가능/재기동 불필요.
650
721
  sharedMemorySize (int): 공유 메모리 크기. 기본 0.
651
722
  스펙: 기본 DISABLED (0) · 범위 0~9223372036854775807 · 단위 byte · 변경 불가.
652
- numberOfSegment (int): **세그먼트**(저장 칸) 개수. 기본 2.
723
+ segments (int): **세그먼트**(저장 칸) 개수. 기본 2.
653
724
  한 큐의 메시지를 나눠 담는 저장 칸의 수다 - 파일 1~N, 메모리,
654
725
  공유메모리가 그 칸이다. **토픽의 파티션과 달리 분산 처리 단위가
655
726
  아니다.** 생성 시에만 지정하고 이후 바꿀 수 없다.
727
+ **개수라 맨 복수형**이다 - 목록은 ``...List`` 접미를 쓴다
728
+ (:attr:`ILQueueRealTimeInfo.segmentInfoList`). 토픽의 ``partitions``
729
+ 와 같은 형식이다.
656
730
  스펙: 기본 2 · 범위 2~99 · 단위 개 · 변경 불가.
657
- numberOfPartition (int): ``numberOfSegment`` 의 **옛 이름**. 읽기·쓰기
731
+ numberOfPartition (int): ``segments`` 의 **옛 이름**. 읽기·쓰기
658
732
  모두 같은 값을 가리키므로 기존 코드는 그대로 돈다. 엔진 7.x(SVN 3448)
659
733
  에서 큐의 "파티션" 이 "세그먼트" 로 바뀌면서 이름이 갈렸다 - 큐의
660
734
  저장 칸과 토픽의 분산 단위가 한 글자 차이로 정반대를 뜻하던 것을
661
- 없앴다. **새 코드는** ``numberOfSegment`` **를 쓴다.**
735
+ 없앴다. **새 코드는** ``segments`` **를 쓴다.**
736
+ **이 이름은 영구히 세그먼트 개수를 가리킨다** - 다른 뜻으로
737
+ 재사용하지 않는다. 큐에 진짜 분산 파티션이 생겨도 그 수는
738
+ **토픽과 같은 이름**(``partitions``)으로 따로 들어온다.
662
739
  스펙: 별칭 · 와이어에는 이름이 실리지 않는다(위치 기반 고정폭).
663
740
  legacyBlob (bool): 이 객체가 **구버전(4096) 블롭**에서 만들어졌는지.
664
741
  엔진 rev 3155 미만이 보낸 응답이면 True 다. 그 경우 ``expiry`` /
665
742
  ``expiredQueue`` / ``deliveryMode`` / ``maxMemorySize`` /
666
- ``sharedMemorySize`` / ``numberOfSegment`` 는 **서버가 준 값이 아니라
743
+ ``sharedMemorySize`` / ``segments`` 는 **서버가 준 값이 아니라
667
744
  기본값**이다 - 구엔진에는 그 설정이 없다.
668
745
  스펙: 서버 응답 길이로 라이브러리가 판단하는 내부 표시 · 앱이 건드리지 않는다.
669
746
  """
@@ -678,12 +755,15 @@ class ILQueueProperty(_AutoAccessor):
678
755
  "expiredQueue": _spec_maxlen(47),
679
756
  }
680
757
 
758
+ #: 0.15.0 이 잠깐 쓴 이름. 그 판에서만 살았고 0.16.0 에서 ``segments`` 가 됐다.
759
+ _RENAMED = {"numberOfSegment": ("segments", "0.16.0")}
760
+
681
761
  @property
682
762
  def numberOfPartition(self) -> int:
683
- """``numberOfSegment`` 의 **옛 이름**. 읽기·쓰기 모두 같은 값이다.
763
+ """``segments`` 의 **옛 이름**. 읽기·쓰기 모두 같은 값이다.
684
764
 
685
765
  Returns:
686
- int: ``numberOfSegment`` 와 같은 값.
766
+ int: ``segments`` 와 같은 값.
687
767
 
688
768
  Note:
689
769
  클래스 레벨 ``property`` 라서 대입도 받는다
@@ -693,12 +773,19 @@ class ILQueueProperty(_AutoAccessor):
693
773
 
694
774
  **와이어에는 이름이 실리지 않는다** - 큐 속성 직렬화는 위치 기반
695
775
  고정폭이라 이 개명은 이름 층만의 변경이고 엔진 판과 무관하다.
776
+
777
+ **이 별칭은 영구히 세그먼트 수를 가리킨다.** 뜻을 바꿔 재사용하지
778
+ 않는다 - 재사용은 제거보다 나쁘기 때문이다. 제거는 ``AttributeError``
779
+ 로 그 자리에서 터지지만, 재사용은 **옛 코드가 조용히 다른 수를
780
+ 읽는다.** 큐의 분산 파티션 수는 ``partitions``
781
+ 으로 들어온다 - 토픽과 같은 이름 ``partitions`` 다
782
+ (엔진 ilsc ``PARTITIONS(n)`` · 컨피그 XML ``Partitions``).
696
783
  """
697
- return self.numberOfSegment
784
+ return self.segments
698
785
 
699
786
  @numberOfPartition.setter
700
787
  def numberOfPartition(self, value: int) -> None:
701
- self.numberOfSegment = value
788
+ self.segments = value
702
789
 
703
790
  def __init__(
704
791
  self,
@@ -734,7 +821,7 @@ class ILQueueProperty(_AutoAccessor):
734
821
  self.deliveryMode = ILC.MIMQ_DELIVERY_MODE_DEPENDS_ON_MSG
735
822
  self.maxMemorySize = 10485760
736
823
  self.sharedMemorySize = 0
737
- self.numberOfSegment = 2
824
+ self.segments = 2
738
825
  #: 구버전(4096) 블롭에서 만들어졌는지. 내부 판별용.
739
826
  self.legacyBlob = False
740
827
 
@@ -808,7 +895,7 @@ class ILQueueProperty(_AutoAccessor):
808
895
  offset += 20
809
896
  self.sharedMemorySize = ba_pick_long(ba, offset, 20)
810
897
  offset += 20
811
- self.numberOfSegment = ba_pick_int(ba, offset, 10)
898
+ self.segments = ba_pick_int(ba, offset, 10)
812
899
  offset += 10
813
900
  offset += 228
814
901
  # ---- 공통 접미 (2142) ----
@@ -835,7 +922,7 @@ class ILQueueProperty(_AutoAccessor):
835
922
  보고 :class:`ILAdminQmgr` 가 정한다.
836
923
 
837
924
  구버전 레이아웃에는 ``expiry`` / ``expiredQueue`` / ``deliveryMode`` /
838
- ``maxMemorySize`` / ``sharedMemorySize`` / ``numberOfSegment`` 자리가
925
+ ``maxMemorySize`` / ``sharedMemorySize`` / ``segments`` 자리가
839
926
  **없다.** 그 값들은 실리지 않고 버려진다 - 구엔진이 모르는 설정이다.
840
927
  """
841
928
  if legacy:
@@ -879,7 +966,7 @@ class ILQueueProperty(_AutoAccessor):
879
966
  offset += 20
880
967
  ba_merge(self.sharedMemorySize, ba, offset, 20)
881
968
  offset += 20
882
- ba_merge(self.numberOfSegment, ba, offset, 10)
969
+ ba_merge(self.segments, ba, offset, 10)
883
970
  offset += 10
884
971
  offset += 228
885
972
  ba_merge(self.incomingDelayDepth, ba, offset, 10)
@@ -1020,7 +1107,7 @@ class ILQueueProperty(_AutoAccessor):
1020
1107
  + str(self.sharedMemorySize)
1021
1108
  + "bytes)\n"
1022
1109
  + "\tNUM-SEGMENT ("
1023
- + str(self.numberOfSegment)
1110
+ + str(self.segments)
1024
1111
  + ") DELAY(over "
1025
1112
  + str(self.incomingDelayDepth)
1026
1113
  + "depth, "
@@ -2014,6 +2101,14 @@ class ILQueueRealTimeInfo(_AutoAccessor):
2014
2101
  채우지 않는다(직렬화에서 그 180바이트를 건너뛴다). 그래서 구엔진에
2015
2102
  붙었을 때만 값이 온다.
2016
2103
 
2104
+ ★ **그 180바이트는 빈 자리가 아니다.** 오프셋 30~210 이고, 이 네 필드가
2105
+ 정확히 그 폭을 채운다(20+20+70+70). 엔진이 건너뛰는 구간과 같은 자리이니
2106
+ **예약 공간으로 보이지만 임자가 있다** - 이 클라는 지금도 그 자리를
2107
+ 파싱한다. 여기에 새 필드를 실으면 옛 클라는 0 이 아니라 **쓰레기를 값으로**
2108
+ 읽고(문자열 칸이라 예외도 안 난다), 그 값이 :meth:`__str__` 의 ``LASTPUT``
2109
+ 줄로 그대로 나간다. 재사용하려면 **수신자가 새 뜻을 안다고 말한 뒤**
2110
+ 여야 한다(엔진 능력 선언).
2111
+
2017
2112
  6.3.3+ 에서 "누가 마지막으로 이 큐를 건드렸는지" 를 보려면 세션 쪽을
2018
2113
  보라 - :meth:`ILAdminQmgr.getSessionList` 가 주는
2019
2114
  :class:`ILSessionProperty` 의 ``lastAccessObject`` 가 그 정보를 세션
@@ -2042,33 +2137,46 @@ class ILQueueRealTimeInfo(_AutoAccessor):
2042
2137
  스펙: 기본 0 · 범위 0 이상 · 단위 건 · 변경 불가(ReadOnly).
2043
2138
  uncommittedGet (int): 아직 커밋되지 않은 get 건수. 기본 0.
2044
2139
  스펙: 기본 0 · 범위 0 이상 · 단위 건 · 변경 불가(ReadOnly).
2045
- segments (list[SegmentItem]): **세그먼트별** 상세. 기본 빈 목록.
2140
+ segmentInfoList (list[SegmentItem]): **세그먼트별** 상세. 기본 빈 목록.
2141
+ 목록이라 ``...List`` 접미를 쓴다 - 개수를 뜻하는 맨 복수형
2142
+ (:attr:`ILQueueProperty.segments`)과 구별된다.
2046
2143
  스펙: 기본 빈 목록 · 범위 세그먼트 수만큼 · 변경 불가(ReadOnly).
2047
- partitions (list[SegmentItem]): ``segments`` 의 **옛 이름**. 읽기·쓰기 모두
2144
+ partitions (list[SegmentItem]): ``segmentInfoList`` 의 **옛 이름**. 읽기·쓰기 모두
2048
2145
  같은 목록을 가리킨다. 엔진 7.x(SVN 3448)에서 큐의 저장 칸이
2049
2146
  "세그먼트" 가 되면서 이름이 갈렸다 - 토픽의 ``getPartitions()`` 는
2050
- **분산 단위**라 뜻이 다르다. **새 코드는** ``segments`` **를 쓴다.**
2147
+ **분산 단위**라 뜻이 다르다. **새 코드는** ``segmentInfoList`` **를 쓴다.**
2148
+ **이 이름은 영구히 세그먼트 목록을 가리킨다** - 다른 뜻으로
2149
+ 재사용하지 않는다.
2051
2150
  스펙: 별칭 · 와이어에는 이름이 실리지 않는다.
2052
2151
  """
2053
2152
 
2153
+ #: 0.15.0 이 잠깐 쓴 이름. 그 판에서만 살았고 0.16.0 에서 ``segmentInfoList`` 가 됐다.
2154
+ #: 이 이름을 비워 둔 덕에 :attr:`ILQueueProperty.segments`(세그먼트 **개수**)와
2155
+ #: 겹치지 않는다 - 같은 이름이 클래스마다 다른 뜻이 되는 것을 막는다.
2156
+ _RENAMED = {"segments": ("segmentInfoList", "0.16.0")}
2157
+
2054
2158
  @property
2055
2159
  def partitions(self) -> "List[SegmentItem]":
2056
- """``segments`` 의 **옛 이름**. 같은 목록을 가리킨다.
2160
+ """``segmentInfoList`` 의 **옛 이름**. 같은 목록을 가리킨다.
2057
2161
 
2058
2162
  Returns:
2059
- list[SegmentItem]: ``segments`` 와 같은 목록 객체.
2163
+ list[SegmentItem]: ``segmentInfoList`` 와 같은 목록 객체.
2060
2164
 
2061
2165
  Note:
2062
2166
  :class:`_AutoAccessor` 가 만들어 주는 ``getPartitions()`` /
2063
2167
  ``setPartitions()`` 도 이 별칭을 통과한다. **토픽의**
2064
2168
  ``ILTopic.getPartitions()`` **와 이름은 같지만 뜻이 다르다** -
2065
2169
  저쪽은 분산 처리 단위고 이쪽은 한 노드 안의 저장 칸이다.
2170
+
2171
+ **이 별칭은 영구히 세그먼트 목록을 가리킨다.** 큐에 분산 파티션이
2172
+ 생겨도 이 이름을 그쪽으로 돌리지 않는다 - 그러면 옛 코드가 조용히
2173
+ 다른 것을 읽는다.
2066
2174
  """
2067
- return self.segments
2175
+ return self.segmentInfoList
2068
2176
 
2069
2177
  @partitions.setter
2070
2178
  def partitions(self, value: "List[SegmentItem]") -> None:
2071
- self.segments = value
2179
+ self.segmentInfoList = value
2072
2180
 
2073
2181
  # [spec-check] 문자열 상한 = 와이어 폭 - 1 (엔진이 C 문자열로 읽는다)
2074
2182
  _SPEC = {
@@ -2097,7 +2205,7 @@ class ILQueueRealTimeInfo(_AutoAccessor):
2097
2205
  self.numberOfChannel = 0
2098
2206
  self.uncommittedPut = 0
2099
2207
  self.uncommittedGet = 0
2100
- self.segments: List[SegmentItem] = []
2208
+ self.segmentInfoList: List[SegmentItem] = []
2101
2209
 
2102
2210
  if ba is None:
2103
2211
  return
@@ -2137,7 +2245,7 @@ class ILQueueRealTimeInfo(_AutoAccessor):
2137
2245
  item = SegmentItem(
2138
2246
  ba_pick_bytes(ba, offset, ILC.MIMQ_VO_SEGMENT_ITEM_LEN)
2139
2247
  )
2140
- self.segments.append(item)
2248
+ self.segmentInfoList.append(item)
2141
2249
  offset += ILC.MIMQ_VO_SEGMENT_ITEM_LEN
2142
2250
  except Exception as exc:
2143
2251
  raise ILException(exc) from exc
@@ -2153,8 +2261,8 @@ class ILQueueRealTimeInfo(_AutoAccessor):
2153
2261
  일은 거의 없다.
2154
2262
  """
2155
2263
  buffer_length = ILC.MIMQ_VO_QUEUE_INFO_LEN + ILC.MIMQ_LIST_ITEM_COUNT_LENGTH
2156
- if self.segments:
2157
- buffer_length += len(self.segments) * ILC.MIMQ_VO_SEGMENT_ITEM_LEN
2264
+ if self.segmentInfoList:
2265
+ buffer_length += len(self.segmentInfoList) * ILC.MIMQ_VO_SEGMENT_ITEM_LEN
2158
2266
  ba = bytearray(buffer_length)
2159
2267
  offset = 0
2160
2268
  ba_merge(self.curDepth, ba, offset, 10)
@@ -2177,9 +2285,9 @@ class ILQueueRealTimeInfo(_AutoAccessor):
2177
2285
  offset += 10
2178
2286
  ba_merge(self.uncommittedGet, ba, offset, 10)
2179
2287
  offset += 10
2180
- ba_merge(len(self.segments), ba, offset, 5)
2288
+ ba_merge(len(self.segmentInfoList), ba, offset, 5)
2181
2289
  offset += 5
2182
- for item in self.segments:
2290
+ for item in self.segmentInfoList:
2183
2291
  ba_merge(item.get_serialized(), ba, offset, ILC.MIMQ_VO_SEGMENT_ITEM_LEN)
2184
2292
  offset += ILC.MIMQ_VO_SEGMENT_ITEM_LEN
2185
2293
  return bytes(ba)
@@ -2205,7 +2313,7 @@ class ILQueueRealTimeInfo(_AutoAccessor):
2205
2313
  ret += f"ACCESS(Client {self.numberOfClient}, Channel {self.numberOfChannel})\n"
2206
2314
  ret += f"TRANSACTED(Put {self.uncommittedPut}, Get {self.uncommittedGet})\n"
2207
2315
  ret += "Segments ---------------------------------------------------------\n"
2208
- for segment in self.segments:
2316
+ for segment in self.segmentInfoList:
2209
2317
  ret += " " + str(segment)
2210
2318
  return ret
2211
2319
 
@@ -2225,7 +2333,7 @@ class ILQueueRealTimeInfo(_AutoAccessor):
2225
2333
  (6.3.3 에서 별도 조회로 분리됐다). 그래서 같은 응답으로 속성 객체와
2226
2334
  이 객체를 모두 채울 수 있다.
2227
2335
 
2228
- :attr:`segments` 는 **빈 목록**이 된다. 저장 칸 나누기는 6.3.3 에서
2336
+ :attr:`segmentInfoList` 는 **빈 목록**이 된다. 저장 칸 나누기는 6.3.3 에서
2229
2337
  들어온 기능이라 구엔진 큐에는 세그먼트라는 개념 자체가 없다 - 누락이
2230
2338
  아니라 사실이다.
2231
2339
  """
@@ -2243,7 +2351,7 @@ class ILQueueRealTimeInfo(_AutoAccessor):
2243
2351
  # 현행 유량 조회(ILQueueFlow)는 **구간별** 값이라 의미가 달라 쓰지 않는다.
2244
2352
  info.uncommittedPut = ba_pick_int(ba, o + 300, 10)
2245
2353
  info.uncommittedGet = ba_pick_int(ba, o + 310, 10)
2246
- info.segments = []
2354
+ info.segmentInfoList = []
2247
2355
  return info
2248
2356
 
2249
2357
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jetstream-api
3
- Version: 0.15.0
3
+ Version: 0.16.0
4
4
  Summary: Python client API for iLink M.O.M. (Message Oriented Middleware)
5
5
  Author: snowjeans
6
6
  License: Boost Software License - Version 1.0 - August 17th, 2003
@@ -60,6 +60,32 @@ lz4 배치 압축을 쓰려면 `pip install "jetstream-api[lz4]"`, zstd 배치
60
60
  ## 설치 방법
61
61
  pip install jetstream-api
62
62
 
63
+ ## 0.16.0 변경 - 세그먼트 이름을 토픽과 같은 형식으로, 오타 대입 거부 (자바 v2.12.0 과 같음)
64
+
65
+ - **이름 규칙이 정해졌습니다 - 개수는 맨 복수형, 목록은 `...List` 접미.** 토픽이 `partitions` 를 쓰는 형식 그대로입니다.
66
+ 0.15.0 이 하루 쓴 이름 둘을 여기로 옮깁니다.
67
+
68
+ | 자리 | 0.15.0 | **0.16.0** |
69
+ |---|---|---|
70
+ | 세그먼트 **개수** (`ILQueueProperty`) | `numberOfSegment` | **`segments`** |
71
+ | 세그먼트 **목록** (`ILQueueRealTimeInfo`) | `segments` | **`segmentInfoList`** |
72
+
73
+ - ★ **0.15.0 의 두 이름은 남기지 않고 지웠습니다.** 남기면 개수에 이름이 셋이 되고, 더 나쁘게는 `segments` 가
74
+ 클래스마다 다른 뜻(개수 vs 목록)이 됩니다. 0.15.0 은 하루짜리였고, 아래 가드 덕분에 **지운 것이 조용하지 않습니다.**
75
+ - **`numberOfPartition` 과 `partitions` 는 그대로 있습니다.** 예전부터 쓰던 이름이라 영구 별칭으로 남습니다.
76
+ - 큐에 진짜 분산 파티션이 생기면 그 수는 **토픽과 같은 이름(`partitions`)** 으로 따로 들어옵니다. 지금 있는 이름을
77
+ 그쪽으로 돌리지 않습니다 - **재사용은 제거보다 나쁩니다.** 제거는 그 자리에서 터지지만 재사용은 조용히 다른 값을 줍니다.
78
+ - **속성 객체가 모르는 필드 이름 대입을 거부합니다.** 지금까지는 `prop.numberOfSegmnet = 4` 같은 오타가 **예외도 없이**
79
+ 쓰레기 속성을 만들고 실제 값은 그대로였습니다 - 읽기는 원래 `AttributeError` 였는데 **쓰기만 침묵**해서 옛 값이 그대로
80
+ 서버로 나갔습니다.
81
+ - 이름이 바뀐 필드는 **무엇으로 바뀌었는지까지** 알려 줍니다:
82
+ `AttributeError: ILQueueProperty has no attribute numberOfSegment - 0.16.0 에서 segments 로 바뀌었다`
83
+ - 정말 임의 속성을 얹어야 하면 `object.__setattr__(obj, name, value)` 로 우회할 수 있습니다. 그 값은 **와이어에 실리지
84
+ 않습니다.**
85
+ - 생성자가 도는 동안은 열려 있습니다(필드를 만들어야 하므로). 상속해 쓰는 응용도 `super().__init__()` 뒤에 자기 필드를
86
+ 만들 수 있습니다.
87
+ - **와이어는 달라지지 않습니다.** 0.15.0 과 바이트가 같습니다(큐 속성 2200 · 구엔진 4096 · 실시간정보). 이 판도 엔진 판을 가리지 않습니다.
88
+
63
89
  ## 0.15.0 변경 - 큐의 "파티션" 이 "세그먼트" 가 됩니다 (자바 v2.11.0 과 같음)
64
90
 
65
91
  - **`ILQueueProperty.numberOfPartition` 이 `numberOfSegment` 로 바뀝니다.** 값도 자리도 그대로이고 **이름만** 바뀝니다.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "jetstream-api"
7
- version = "0.15.0"
7
+ version = "0.16.0"
8
8
  description = "Python client API for iLink M.O.M. (Message Oriented Middleware)"
9
9
  authors = [{name = "snowjeans"}]
10
10
  readme = "README.md"
File without changes