فهرست مقاله
فرض کنید یک مرحلهٔ تحویلِ نرمافزار، ضرایبِ ساختگیِ کالیبراسیون را از بستهای در حافظه میخواند. در فهرست، نامِ آشنای فایل دیده میشود؛ اما اگر همین نام دوبار ثبت شده باشد، نام بهتنهایی عضوِ موردِ نظر را مشخص نمیکند. این درس مسئله را با یک ZIP کوچک بازسازی میکند و پیش از انتخاب، تکرارِ دقیقِ نامها را رد میکند. هیچ خطِ واقعیِ CI، دستگاهِ اندازهگیری یا استخراجِ فایل روی دیسک اجرا نمیشود.
چرا یک نام، هویتِ یک عضو نیست؟

آرشیو را فعلاً فهرستی از ورودیها بدانید، نه دیکشنریِ نام به محتوا. ممکن است دو ورودی، رشتهٔ نامِ برابر و بایتهای متفاوت داشته باشند. تبدیلِ بیبررسیِ این فهرست به یک نگاشت، یکی از آن دو را پنهان میکند. حتی اگر محتوایشان برابر باشد، هنوز دو ورودی وجود دارد و سیاستِ انتخاب باید روشن باشد؛ برابریِ نام، برابریِ هویتِ ورودی را ثابت نمیکند.
در شاهدِ دستی، دو عضوِ همنام داریم: یکی ضریبِ دو و جابهجاییِ منفیِ سه میلیولت دارد و دیگری ضریبِ سه و جابهجاییِ پنج میلیولت. برای ورودیِ ده میلیولت، دو جوابِ حسابیِ هفده و سیوپنج میلیولت به دست میآید. این اختلاف از اندازهگیری یا خطای عددی نیست؛ دو قانونِ تألیفیِ متفاوت در دو عضو ذخیره شدهاند.
طبق مستنداتِ رسمیِ zipfile، خواندنِ عضو میتواند شیءِ ZipInfo بگیرد و این امکان برای نامهای تکراری کاربرد دارد. در شاهد، هر عضو با شیءِ خودش خوانده میشود. به رفتارِ انتخابِ مبتنی بر رشتهٔ نام تکیه نمیکنیم و نمیگوییم اولین یا آخرین عضو، «نسخهٔ معتبر» است. چنین اعتباری از نامِ تکراری به دست نمیآید.
ZipInfo را از فهرستِ خودِ آرشیو بگیریم

تابعِ infolist برای هر عضو یک شیءِ اطلاعاتی میدهد. برنامه، ترتیبِ فهرست، نامِ دقیق، اندازه و header_offset را ثبت میکند. افست، جایگاهِ سرآیندِ عضو برحسبِ بایت است؛ در شاهد، دو نامِ برابر به دو افستِ متفاوت وصلاند. شیءِ انتخابشده از همان آرشیو گرفته میشود و مستقیم به read تحویل داده میشود؛ هیچ ZipInfo حدسی از روی نام ساخته نمیشود.
سندِ قالبِ ZIP از PKWARE، برای هر فایل، سرآیندِ محلی و رکوردِ متناظر در فهرستِ مرکزی تعریف میکند. فهرستِ مرکزی نیز جایگاهِ سرآیندِ محلی را نگه میدارد. این ساختار توضیح میدهد چرا رشتهٔ نام، تمامِ مشخصاتِ یک ورودی نیست. از این سند، قاعدهای عمومی برای ممنوعبودنِ همهٔ نامهای تکراری برداشت نمیکنیم؛ ردِ تکرار، تصمیمِ برنامهٔ ماست.
ترتیبها را یکی نگیریم. همان سند میگوید ترتیبِ رکوردهای مرکزی لزوماً ترتیبِ قرارگرفتنِ دادهها در آرشیو نیست. شمارهٔ ردیفِ گزارش، جایگاه در فهرستِ بازگشتیِ کتابخانه است؛ افست، مکانِ سرآیند است. هیچکدام را شناسهٔ پایدارِ یک عضو در تمامِ بازنویسیهای آینده نمینامیم. جابهجاییِ ورودیها میتواند شماره یا افست را عوض کند، بیآنکه قانونِ کالیبراسیون عوض شود.
در درسِ بستهٔ تکرارپذیرِ gzip، هویتِ محتوای بازشده از بایتهای پوشش جدا بود. اینجا قالب و پرسش متفاوتاند: عضوِ ZIP را پیش از تفسیرِ محتوا مشخص میکنیم. این پیوند از موجودیِ منتشرشده و بدنهٔ ذخیرهشدهٔ قبلی انتخاب شده است؛ دسترسیِ زندهٔ فعلیِ آن در این مرحله هنوز تأیید نشده است.
قراردادِ کوچکِ بستهٔ کالیبراسیون

ورودی، فقط bytes دقیق با حداکثرِ ۴۰۹۶ بایت است. نامِ هدف، رشتهٔ ASCII چاپپذیر با طولِ یک تا چهل است. آرشیو حداکثر هشت عضو و هر عضو حداکثر ۱۲۸ بایت داده دارد. فقط روشِ ZIP_STORED پذیرفته میشود. این سقفها انتخابهای آموزشیاند؛ بودجهٔ عمومیِ حافظه یا تضمینِ ایمنیِ بازکردنِ آرشیوِ ناشناس نیستند.
پس از گرفتنِ فهرست و بررسیِ شمارِ اعضا، نامِ همهٔ ورودیها مقایسه میشود. با اولین تکرارِ دقیق، پذیرش پایان مییابد؛ هنوز هدف انتخاب یا دادهٔ آن خوانده نشده است. این سیاست حتی تکرارِ notes.txt را رد میکند، اگر فایلِ کالیبراسیون اصلاً موجود نباشد. علت، قراردادِ یکتاییِ کلِ بسته است، نه این ادعا که هر کاربردِ ZIP باید همین سیاست را داشته باشد.
«نامِ دقیق» در اینجا رشتهٔ filename است که کتابخانه پس از خواندنِ فراداده در اختیارمان میگذارد؛ مقایسهٔ بایتِ خامِ نام در فهرستِ مرکزی نیست. fixtureهای ما نامِ ASCII و بدونِ بایتِ تهی دارند. نامها به حروفِ کوچک تبدیل و مسیرها عادیسازی نمیشوند. calibration.json، Calibration.json و lab/calibration.json متفاوتاند. پوشه با پایانِ اسلش، با فایلِ بدونِ اسلش برابر نیست و پوشهٔ هدف رد میشود. دربارهٔ همارزیِ مسیرهای دیسک یا Unicode نیز ادعایی نداریم.
فایلِ منتخب، JSON با دقیقاً دو کلیدِ gain و offset_mV است. کلیدِ تکراری رد میشود. ضریب، عددِ صحیحِ بدونِ واحد از صفر تا هشت است؛ جابهجایی و ورودی، اعدادِ صحیح از منفیِ صد تا صد میلیولتاند. bool و float جایِ عددِ صحیح پذیرفته نمیشوند. پاسخ، حاصلِ ضریب در ورودی بهاضافهٔ جابهجایی است و واحدِ آن میلیولت میماند.
در درسِ نسخهٔ کالیبراسیون در کلیدِ کش، وابستگیِ پنهان باعثِ نتیجهٔ کهنه میشد. این مثال کش و سیاستِ تازگی ندارد؛ پیش از محاسبه میپرسد کدام ورودی اصلاً مجاز به انتخاب است. ضریبها و واحدهای ساختگیِ این درس نیز جایگزینِ مرجعِ معتبرِ ضرایب یا تأییدِ دقتِ فیزیکی نیستند.
مثالِ کامل و شاهدِ مستقلِ بایتها

سازندهٔ fixture فقط بافرِ حافظه مینویسد و تاریخِ سرآیند را صریح میدهد. هشدارِ موردِ انتظارِ نامِ تکراری با catch_warnings ثبت و متن و ردهٔ آن بررسی میشود. هشدارها بهطورِ عمومی خاموش نمیشوند؛ هشدارِ اضافی، آزمون را متوقف میکند. پس ساختِ آگاهانهٔ شاهدِ تکراری، با بیاعتنایی به هشدارِ برنامهٔ واقعی برابر نیست.
شاهدِ مستقل از ZipFile، ZipInfo، اعتبارسنجِ اصلی و رمزگشای JSON استفاده نمیکند. روی fixtureهای ساختهشدهٔ خودمان، سرآیندهای محلی را با چیدمانِ مستند و ترتیبِ بایتِ کمارزشاول میخواند و نام، داده و جایگاه را جدا بیرون میآورد. فقط عضوهای ذخیرهایِ بدونِ فیلدِ اضافی و توصیفگر را میشناسد؛ تجزیهگرِ کاملِ ZIP یا آزمونِ احرازِ اصالت نیست.
خانوادهٔ محدود از سه نام و دو محتوای معلوم، همهٔ دنبالههای طولِ صفر تا سه را میسازد: ۲۵۹ آرشیو و ۲۳۳۱ پرسوجو برای سه هدف و سه ورودی. مرجع، تکرار را با مقایسهٔ جفتی تشخیص میدهد و پاسخِ دستی را با جمعِ صحیح میسازد. تمامِ این خانواده یک گروه است. چهارده گروهِ نامدارِ کلِ برنامه، همین خانواده، شاهدهای دستی، مرزها و ردِ ورودیهای نامعتبر را در بر میگیرند.
"""Exact member identity in small synthetic in-memory stored ZIP fixtures.
No extraction, file/network input, authentication, timing or physical readings.
The independent local-header scanner is only an oracle for generated fixtures.
"""
import io
from itertools import product
import json
import platform
import struct
import sys
import warnings
import zipfile
MAX_ARCHIVE_BYTES = 4096
MAX_ENTRIES = 8
MAX_MEMBER_BYTES = 128
MAX_NAME_BYTES = 40
A = b'{"gain":2,"offset_mV":-3}'
B = b'{"gain":3,"offset_mV":5}'
def checked_name(value):
if (type(value) is not str or not 1 <= len(value) <= MAX_NAME_BYTES
or not value.isascii() or any(ord(c) < 32 or ord(c) > 126 for c in value)):
raise ValueError('name')
return value
def unique_json_object(pairs):
result = {}
for key, value in pairs:
if key in result:
raise ValueError('duplicate_json_key')
result[key] = value
return result
def calibration_payload(payload):
try:
data = json.loads(payload.decode('utf-8'), object_pairs_hook=unique_json_object)
except (UnicodeError, json.JSONDecodeError) as error:
raise ValueError('calibration_json') from error
if type(data) is not dict or set(data) != {'gain', 'offset_mV'}:
raise ValueError('calibration_fields')
gain, offset = data['gain'], data['offset_mV']
if type(gain) is not int or not 0 <= gain <= 8:
raise ValueError('gain')
if type(offset) is not int or not -100 <= offset <= 100:
raise ValueError('offset_mV')
return gain, offset
def admit_calibration(archive, target='calibration.json', input_mV=10):
"""Own bounded admission policy, not a general hostile-archive validator."""
if type(archive) is not bytes or len(archive) > MAX_ARCHIVE_BYTES:
raise ValueError('archive_bytes')
checked_name(target)
if type(input_mV) is not int or not -100 <= input_mV <= 100:
raise ValueError('input_mV')
try:
container = zipfile.ZipFile(io.BytesIO(archive), 'r')
except zipfile.BadZipFile as error:
raise ValueError('archive_format') from error
with container:
infos = container.infolist()
if len(infos) > MAX_ENTRIES:
raise ValueError('entry_count')
# Compare library-exposed decoded filename strings, not raw name bytes.
# Global exact-name rejection occurs before target selection or read.
seen = set()
for info in infos:
if info.filename in seen:
raise ValueError('duplicate_member_name')
seen.add(info.filename)
rows = []
for index, info in enumerate(infos):
checked_name(info.filename)
if info.compress_type != zipfile.ZIP_STORED:
raise ValueError('stored_only')
if info.file_size > MAX_MEMBER_BYTES or info.compress_size > MAX_MEMBER_BYTES:
raise ValueError('member_bytes')
if info.is_dir() and info.file_size != 0:
raise ValueError('directory_data')
rows.append({'entry_index': index, 'exact_name': info.filename,
'header_offset_bytes': info.header_offset,
'payload_bytes': info.file_size, 'is_directory': info.is_dir()})
matches = [info for info in infos if info.filename == target]
if not matches:
raise ValueError('target_missing')
selected = matches[0]
if selected.is_dir():
raise ValueError('target_directory')
# Pass the actual object from this archive, never a member-name string.
payload = container.read(selected)
if len(payload) > MAX_MEMBER_BYTES:
raise ValueError('member_bytes')
gain, offset = calibration_payload(payload)
return {'entries_in_library_order': rows,
'selected_exact_name': selected.filename,
'selected_header_offset_bytes': selected.header_offset,
'gain': gain, 'offset_mV': offset, 'input_mV': input_mV,
'output_mV': gain * input_mV + offset}
def stored_fixture(entries, comment=b''):
"""Trusted test construction only. Every warning is captured and checked."""
assert type(entries) is tuple and len(entries) <= 9 and type(comment) is bytes
stream = io.BytesIO()
expected_warnings = []
previous = []
for name, payload in entries:
assert type(name) is str and name.isascii() and type(payload) is bytes
if name in previous:
expected_warnings.append("Duplicate name: " + repr(name))
previous.append(name)
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter('always')
with zipfile.ZipFile(stream, 'w', compression=zipfile.ZIP_STORED) as container:
for name, payload in entries:
info = zipfile.ZipInfo(name, date_time=(2020, 1, 2, 3, 4, 6))
info.compress_type = zipfile.ZIP_STORED
container.writestr(info, payload)
container.comment = comment
assert [str(w.message) for w in caught] == expected_warnings
assert all(w.category is UserWarning for w in caught)
return stream.getvalue(), expected_warnings
def exact_entry_witness(archive):
"""Diagnostic only: retain all objects even when admission would reject."""
with zipfile.ZipFile(io.BytesIO(archive), 'r') as container:
infos = container.infolist()
return [{'entry_index': index, 'exact_name': info.filename,
'header_offset_bytes': info.header_offset,
'payload_hex': container.read(info).hex()}
for index, info in enumerate(infos)]
def local_header_oracle(archive):
"""Generated fixtures only: stored, flags0, no extras/descriptors/ZIP64.
No ZipFile, ZipInfo, main admission/validator or JSON decoder calls.
This is not a general ZIP parser or an integrity/authentication check.
"""
position = 0
result = []
while archive[position:position + 4] == b'PK\x03\x04':
fields = struct.unpack_from('<IHHHHHIIIHH', archive, position)
_, version, flags, method, _, _, _, compressed, size, nlen, extra = fields
assert version <= 20 and flags == method == extra == 0 and compressed == size
start = position + 30 + nlen
name = archive[position + 30:start].decode('ascii')
payload = archive[start:start + size]
assert len(payload) == size
result.append((name, payload, position))
position = start + size
assert archive[position:position + 4] in (b'PK\x01\x02', b'PK\x05\x06')
return result
def oracle_outcome(rows, target, input_mV):
# Pairwise name comparison rather than the production set/ZipInfo path.
if any(rows[left][0] == rows[right][0]
for left in range(len(rows)) for right in range(left + 1, len(rows))):
return ('error', 'duplicate_member_name')
for name, payload, offset in rows:
if name == target:
if payload == A:
return ('ok', sum((input_mV, input_mV)) - 3, offset)
assert payload == B
return ('ok', sum((input_mV, input_mV, input_mV)) + 5, offset)
return ('error', 'target_missing')
def actual_outcome(archive, target, input_mV):
try:
result = admit_calibration(archive, target, input_mV)
except ValueError as error:
return ('error', str(error))
return ('ok', result['output_mV'], result['selected_header_offset_bytes'])
def rejects(call, expected):
try:
call()
except ValueError as error:
return str(error) == expected
return False
def run_example():
checks = {}
def check(name, value):
assert type(value) is bool and value, name
checks[name] = value
unique, no_warnings = stored_fixture((('notes.txt', b'memo'), ('calibration.json', A)))
manual = admit_calibration(unique)
check('manual_unique_calibration_has_integer_millivolt_answer',
manual['gain'] == 2 and manual['offset_mV'] == -3
and manual['input_mV'] == 10 and manual['output_mV'] == 17
and manual['entries_in_library_order'][1]['entry_index'] == 1 and no_warnings == [])
duplicate, expected_warning = stored_fixture((('calibration.json', A), ('calibration.json', B)))
witness = exact_entry_witness(duplicate)
check('actual_ZipInfo_objects_keep_duplicate_payloads_and_offsets_distinct',
[row['exact_name'] for row in witness] == ['calibration.json'] * 2
and [row['payload_hex'] for row in witness] == [A.hex(), B.hex()]
and witness[0]['header_offset_bytes'] == 0 < witness[1]['header_offset_bytes'])
first, _ = stored_fixture((('calibration.json', A), ('calibration.json', B), ('notes.txt', b'n')))
last, _ = stored_fixture((('notes.txt', b'n'), ('calibration.json', B), ('calibration.json', A)))
check('duplicate_first_or_last_is_rejected_without_member_name_lookup',
rejects(lambda: admit_calibration(first), 'duplicate_member_name')
and rejects(lambda: admit_calibration(last), 'duplicate_member_name'))
same, same_warning = stored_fixture((('calibration.json', A), ('calibration.json', A)))
check('identical_duplicate_payloads_still_fail_owned_identity_policy',
rejects(lambda: admit_calibration(same), 'duplicate_member_name')
and expected_warning == same_warning == ["Duplicate name: 'calibration.json'"])
unrelated, unrelated_warning = stored_fixture((('notes.txt', b'a'), ('notes.txt', b'b')))
check('global_duplicate_scan_precedes_even_a_missing_target',
rejects(lambda: admit_calibration(unrelated), 'duplicate_member_name')
and unrelated_warning == ["Duplicate name: 'notes.txt'"])
reordered, _ = stored_fixture((('calibration.json', A), ('notes.txt', b'memo')))
reordered_result = admit_calibration(reordered)
check('unique_reordering_preserves_value_not_enumeration_or_offset',
reordered_result['output_mV'] == manual['output_mV'] == 17
and reordered_result['selected_header_offset_bytes'] == 0
and manual['selected_header_offset_bytes'] > 0
and [x['exact_name'] for x in reordered_result['entries_in_library_order']]
== ['calibration.json', 'notes.txt'])
folders, _ = stored_fixture((('calibration', A), ('calibration/', b'')))
folder_result = admit_calibration(folders, 'calibration')
check('directory_record_and_file_are_distinct_exact_names',
folder_result['output_mV'] == 17
and folder_result['entries_in_library_order'][1]['is_directory'] is True
and rejects(lambda: admit_calibration(folders, 'calibration/'), 'target_directory'))
nested, _ = stored_fixture((('calibration.json', A), ('lab/calibration.json', B), ('Calibration.json', B)))
check('nested_and_case_distinct_names_are_not_normalized',
admit_calibration(nested)['output_mV'] == 17
and admit_calibration(nested, 'lab/calibration.json')['output_mV'] == 35
and admit_calibration(nested, 'Calibration.json')['output_mV'] == 35)
class BytesChild(bytes):
pass
class IntChild(int):
pass
consumed = []
def lazy():
consumed.append(True)
yield b'x'
archive_invalids = ('zip', None, True, bytearray(unique), memoryview(unique), BytesChild(unique), lazy())
name_invalids = (None, True, '', 'x' * 41, 'cal\x00.json', '\u03b1.json')
input_invalids = (True, 10.0, IntChild(10), -101, 101, None)
check('strict_public_types_bounds_and_no_generator_consumption',
all(rejects(lambda x=x: admit_calibration(x), 'archive_bytes') for x in archive_invalids)
and all(rejects(lambda x=x: admit_calibration(unique, x), 'name') for x in name_invalids)
and all(rejects(lambda x=x: admit_calibration(unique, input_mV=x), 'input_mV') for x in input_invalids)
and consumed == [])
long_name = 'x' * 35 + '.json'
long_payload = A + b' ' * (MAX_MEMBER_BYTES - len(A))
endpoints, _ = stored_fixture(((long_name, long_payload),))
base, _ = stored_fixture((('calibration.json', A),))
padded, _ = stored_fixture((('calibration.json', A),), b'x' * (MAX_ARCHIVE_BYTES - len(base)))
eight, _ = stored_fixture(tuple(('n' + str(i) + '.json', A) for i in range(8)))
nine, _ = stored_fixture(tuple(('n' + str(i) + '.json', A) for i in range(9)))
too_big_member, _ = stored_fixture((('calibration.json', b' ' * 129),))
too_long_name, _ = stored_fixture((('x' * 36 + '.json', A),))
check('owned_archive_entry_name_and_member_caps_are_inclusive',
len(padded) == 4096 and admit_calibration(padded)['output_mV'] == 17
and rejects(lambda: admit_calibration(padded + b'x'), 'archive_bytes')
and admit_calibration(endpoints, long_name, -100)['output_mV'] == -203
and admit_calibration(eight, 'n7.json')['output_mV'] == 17
and rejects(lambda: admit_calibration(nine, 'n7.json'), 'entry_count')
and rejects(lambda: admit_calibration(too_big_member), 'member_bytes')
and rejects(lambda: admit_calibration(too_long_name), 'name'))
bad_json = ((b'no', 'calibration_json'), (b'\xff', 'calibration_json'),
(b'[]', 'calibration_fields'), (b'null', 'calibration_fields'),
(b'{"gain":2}', 'calibration_fields'),
(b'{"gain":2,"offset_mV":0,"extra":1}', 'calibration_fields'),
(b'{"gain":true,"offset_mV":0}', 'gain'),
(b'{"gain":2.0,"offset_mV":0}', 'gain'),
(b'{"gain":9,"offset_mV":0}', 'gain'),
(b'{"gain":-1,"offset_mV":0}', 'gain'),
(b'{"gain":2,"offset_mV":false}', 'offset_mV'),
(b'{"gain":2,"offset_mV":101}', 'offset_mV'),
(b'{"gain":2,"offset_mV":-101}', 'offset_mV'),
(b'{"gain":2,"gain":3,"offset_mV":0}', 'duplicate_json_key'))
json_ok = True
for payload, message in bad_json:
data, _ = stored_fixture((('calibration.json', payload),))
json_ok = json_ok and rejects(lambda data=data: admit_calibration(data), message)
extremes, _ = stored_fixture((('calibration.json', b'{"gain":8,"offset_mV":100}'),))
zero, _ = stored_fixture((('calibration.json', b'{"gain":0,"offset_mV":-100}'),))
check('calibration_JSON_shape_duplicate_keys_integer_types_and_endpoints',
bool(json_ok) and admit_calibration(extremes, input_mV=100)['output_mV'] == 900
and admit_calibration(zero, input_mV=-100)['output_mV'] == -100)
# A deliberately changed method field is rejected before any payload read.
method_changed = bytearray(base)
central = method_changed.index(b'PK\x01\x02')
struct.pack_into('<H', method_changed, 8, 99)
struct.pack_into('<H', method_changed, central + 10, 99)
empty, _ = stored_fixture(())
check('invalid_container_empty_archive_and_outside_stored_profile_reject',
rejects(lambda: admit_calibration(b'not a zip'), 'archive_format')
and rejects(lambda: admit_calibration(empty), 'target_missing')
and rejects(lambda: admit_calibration(bytes(method_changed)), 'stored_only'))
before = bytes(unique)
changed = admit_calibration(unique)
changed['entries_in_library_order'][0]['exact_name'] = 'caller changed copy'
changed['gain'] = 999
fresh = admit_calibration(unique)
check('fresh_result_mappings_and_exact_archive_bytes_are_preserved',
unique == before and fresh == manual and fresh is not changed
and fresh['entries_in_library_order'][0] is not changed['entries_in_library_order'][0])
names = ('calibration.json', 'other.json', 'lab/calibration.json')
choices = tuple((name, payload) for name in names for payload in (A, B))
profiles = queries = warning_count = 0
for length in range(4):
for entries in product(choices, repeat=length):
archive, fixture_warnings = stored_fixture(entries)
reference = local_header_oracle(archive)
assert [(name, payload) for name, payload, _ in reference] == list(entries)
for target in names:
for value in (-1, 0, 10):
assert actual_outcome(archive, target, value) == oracle_outcome(reference, target, value)
queries += 1
profiles += 1
warning_count += len(fixture_warnings)
check('independent_generated_local_header_family_is_ONE_group',
profiles == 259 and queries == 2331)
assert len(checks) == 14
return {'runtime': {'python': platform.python_version(), 'implementation': platform.python_implementation()},
'units': {'gain': 'unitless integer', 'input_offset_output': 'integer mV', 'sizes_and_offsets': 'byte'},
'limits': {'archive_bytes': 4096, 'entries': 8, 'member_bytes': 128, 'name_ASCII_bytes': 40,
'gain': [0, 8], 'offset_mV': [-100, 100], 'input_mV': [-100, 100]},
'policy': 'Reject every duplicate exact member name before target selection; no normalization or case folding.',
'manual_unique_result': manual, 'manual_reordered_result': reordered_result,
'manual_duplicate_entry_witness': witness,
'manual_duplicate_expected_warnings': expected_warning,
'duplicate_name_based_ZipFile_reads': 0,
'independent_family': {'profiles_inside_ONE_group': profiles, 'queries_inside_ONE_group': queries,
'expected_duplicate_warnings_captured_and_checked': warning_count},
'invalid_public_argument_cases_inside_ONE_group': len(archive_invalids) + len(name_invalids) + len(input_invalids),
'invalid_JSON_cases_inside_ONE_group': len(bad_json),
'meaningful_named_groups': len(checks), 'checks': checks,
'scope': 'Generated in-memory stored ZIP fixtures only. No disk extraction, network, CRC authentication, normalized-path uniqueness, hostile-archive resource-safety, physical calibration or benchmark claim.'}
if __name__ == '__main__':
sys.stdout.buffer.write((json.dumps(run_example(), ensure_ascii=True, indent=2, allow_nan=False) + '\n').encode('utf-8'))
{
"runtime": {
"python": "3.14.5",
"implementation": "CPython"
},
"units": {
"gain": "unitless integer",
"input_offset_output": "integer mV",
"sizes_and_offsets": "byte"
},
"limits": {
"archive_bytes": 4096,
"entries": 8,
"member_bytes": 128,
"name_ASCII_bytes": 40,
"gain": [
0,
8
],
"offset_mV": [
-100,
100
],
"input_mV": [
-100,
100
]
},
"policy": "Reject every duplicate exact member name before target selection; no normalization or case folding.",
"manual_unique_result": {
"entries_in_library_order": [
{
"entry_index": 0,
"exact_name": "notes.txt",
"header_offset_bytes": 0,
"payload_bytes": 4,
"is_directory": false
},
{
"entry_index": 1,
"exact_name": "calibration.json",
"header_offset_bytes": 43,
"payload_bytes": 25,
"is_directory": false
}
],
"selected_exact_name": "calibration.json",
"selected_header_offset_bytes": 43,
"gain": 2,
"offset_mV": -3,
"input_mV": 10,
"output_mV": 17
},
"manual_reordered_result": {
"entries_in_library_order": [
{
"entry_index": 0,
"exact_name": "calibration.json",
"header_offset_bytes": 0,
"payload_bytes": 25,
"is_directory": false
},
{
"entry_index": 1,
"exact_name": "notes.txt",
"header_offset_bytes": 71,
"payload_bytes": 4,
"is_directory": false
}
],
"selected_exact_name": "calibration.json",
"selected_header_offset_bytes": 0,
"gain": 2,
"offset_mV": -3,
"input_mV": 10,
"output_mV": 17
},
"manual_duplicate_entry_witness": [
{
"entry_index": 0,
"exact_name": "calibration.json",
"header_offset_bytes": 0,
"payload_hex": "7b226761696e223a322c226f66667365745f6d56223a2d337d"
},
{
"entry_index": 1,
"exact_name": "calibration.json",
"header_offset_bytes": 71,
"payload_hex": "7b226761696e223a332c226f66667365745f6d56223a357d"
}
],
"manual_duplicate_expected_warnings": [
"Duplicate name: 'calibration.json'"
],
"duplicate_name_based_ZipFile_reads": 0,
"independent_family": {
"profiles_inside_ONE_group": 259,
"queries_inside_ONE_group": 2331,
"expected_duplicate_warnings_captured_and_checked": 204
},
"invalid_public_argument_cases_inside_ONE_group": 19,
"invalid_JSON_cases_inside_ONE_group": 14,
"meaningful_named_groups": 14,
"checks": {
"manual_unique_calibration_has_integer_millivolt_answer": true,
"actual_ZipInfo_objects_keep_duplicate_payloads_and_offsets_distinct": true,
"duplicate_first_or_last_is_rejected_without_member_name_lookup": true,
"identical_duplicate_payloads_still_fail_owned_identity_policy": true,
"global_duplicate_scan_precedes_even_a_missing_target": true,
"unique_reordering_preserves_value_not_enumeration_or_offset": true,
"directory_record_and_file_are_distinct_exact_names": true,
"nested_and_case_distinct_names_are_not_normalized": true,
"strict_public_types_bounds_and_no_generator_consumption": true,
"owned_archive_entry_name_and_member_caps_are_inclusive": true,
"calibration_JSON_shape_duplicate_keys_integer_types_and_endpoints": true,
"invalid_container_empty_archive_and_outside_stored_profile_reject": true,
"fresh_result_mappings_and_exact_archive_bytes_are_preserved": true,
"independent_generated_local_header_family_is_ONE_group": true
},
"scope": "Generated in-memory stored ZIP fixtures only. No disk extraction, network, CRC authentication, normalized-path uniqueness, hostile-archive resource-safety, physical calibration or benchmark claim."
}
نسخهٔ اجرای واقعی در خروجی ثبت میشود؛ مستنداتِ خواندهشده نسخهٔ ۳٫۱۴٫۹ را نشان میدهند. APPNOTE نسخهٔ ۶٫۳٫۱۰ با تاریخِ بازنگریِ اولِ نوامبرِ ۲۰۲۲ است؛ تاریخِ مراجعهٔ این درس، بیستویکمِ اکتبرِ ۲۰۲۶ است. این سه تاریخ یا نسخه، جانشینِ هم نیستند. خروجی از کانالِ بایتی با UTF-8 و LF نوشته میشود و نتیجهٔ کامل، قابلِ مقایسه با شاهدهای همین اجراست.
چهار تمرینِ پاسخدار و مرزِ نتیجه

پرسش اول: اگر دو عضوِ همنام، بایتهای یکسان داشته باشند چه میشود؟ پاسخ: در این قرارداد باز هم رد میشوند. تابع دربارهٔ یک عضوِ یکتا تصمیم میگیرد، نه صرفاً یکیبودنِ دادهها. یکسانیِ محتوا، تعدادِ ورودیها را تغییر نمیدهد. کد این حالت را جدا از شاهدِ دو محتوای متفاوت میسنجد و برای هردو، همان خطای سیاستی را انتظار دارد.
پرسش دوم: با جابهجاییِ دو عضوِ یکتا، چه چیزی باید ثابت بماند؟ پاسخ: اگر نامِ دقیق و محتوای کالیبراسیون ثابت باشند، جوابِ هفده میلیولت ثابت میماند؛ شمارهٔ ردیف یا افست لازم نیست ثابت بماند. آزمون، این معیارها را جدا مقایسه میکند. جابهجایی را نشانهٔ تغییرِ قانون نمینامیم و از برابریِ جواب هم برابریِ کلِ بایتهای آرشیو نتیجه نمیگیریم.
پرسش سوم: آیا نامِ تودرتو همان نامِ کوتاه است؟ پاسخ: خیر؛ در مقایسهٔ دقیق، lab/calibration.json با calibration.json متفاوت است. مثال برای اولی سیوپنج و برای دومی هفده میلیولت میدهد. این فقط قراردادِ انتخابِ رشتهٔ کامل است. اگر محصول به عادیسازی، مقایسهٔ بیحساسیت به بزرگیِ حروف یا قواعدِ استخراج نیاز داشته باشد، باید آن قرارداد را جدا طراحی و بررسی کند.
پرسش چهارم: چرا با وجودِ ZipInfo باز هم تکرار را رد میکنیم؟ پاسخ: ZipInfo امکانِ خواندنِ عضوِ مشخص را میدهد، اما تعیین نمیکند کدام کالیبراسیون برای کارِ ما معتبر است. سیاستِ بستهٔ حاضر، ابهام را پیش از محاسبه رد میکند. CRC، نام و افست نیز هویتِ نویسنده را اثبات نمیکنند؛ قبولیِ این چهارده گروه، دربارهٔ امنیتِ کامل، منبعِ ضرایب، کارایی یا صحتِ اندازهگیری نتیجهای ندارد.
منابع و مطالعهٔ بیشتر
بررسی منابع: ۲۹ مهر ۱۴۰۵. تحلیلها و پیشنهادهای اجرایی، جمعبندی نویسندهاند.

