بازگشت به مهندسی مدرن و کار با هوش مصنوعی · فصل ۵ — Shell، Workspace، Lockfile و Build Closure · 25
Python Environments با uv و Wheelhouse
میتواند «Python Environments با uv و Wheelhouse» را در یک workspace محدود طوری پیکربندی کند که dependency/toolchain state قابل تکرار و قابل بررسی باشد.
Python environments with uv and a target-scoped wheelhouse — en-US
خلاصهٔ درس
میتواند «Python Environments با uv و Wheelhouse» را در یک workspace محدود طوری پیکربندی کند که dependency/toolchain state قابل تکرار و قابل بررسی باشد.
خروجی این درس
میتواند «Python Environments با uv و Wheelhouse» را در یک workspace محدود طوری پیکربندی کند که dependency/toolchain state قابل تکرار و قابل بررسی باشد.
یک .venv سالم میتواند مسیر بازسازی خراب را پنهان کند
پروژهای pyproject.toml، فایل uv.lock و محیط مجازی فعالی دارد که وابستگی را بدون خطا import میکند. حالا تنها wheel محلی موردنیاز هدف حذف میشود. محیط گرم هنوز import را انجام میدهد، اما بازسازی آفلاین از یک محیط تمیز دیگر ممکن نیست. import موفق فقط وضعیت فعلی را ثابت میکند؛ قابلیت بازسازی را ثابت نمیکند.
خروجی این درس Python Environment Closure Record v1 است: نیت پروژه، تازگی lock، هویت Python و uv، هویت target، inventory فایلهای محلی، وضعیت clean environment، نتیجه offline، لایه شکست و مرزهای سیستمی باقیمانده را کنار هم ثبت میکند.
سه مسیر، یک سطح شواهد
در مسیر Foundation ابتدا مرزها را روی نقشه مشخص کن. در Repair فقط یک mismatch مربوط به lock، interpreter یا artifact را جدا کن. در Fast Path میتوانی walkthrough دستورات را حذف کنی، اما hashها، هویت ابزار/هدف، بازسازی تمیز، mutation و residual risk باید باقی بمانند.
مدل ذهنی: project → lock → interpreter/target → artifacts → clean environment
پنج لایه را یکی نکن. pyproject.toml نیت وابستگی را میگوید. uv.lock وضعیت resolveشده پروژه را ثبت میکند، نه یک image از OS یا interpreter. Python انتخابشده و target، محدودیت سازگاری را تعیین میکنند. مجموعه artifact محلی باید واقعاً distribution سازگار با همان target داشته باشد. در نهایت، شواهد بازسازی باید از محیط تمیز بیاید؛ .venv گرم ممکن است بستهای را نگه داشته باشد که artifact منبع آن دیگر وجود ندارد.
کتابخانههای native سیستم، compiler، driver و منابع مشابه خارج از claim این درساند مگر اینکه صریحاً در artifactهای Python مدل شده باشند.
ساخت Python Environment Closure Record v1
برای هر probe این فیلدها را ثبت کن: pyproject_hash، uv_lock_hash، lock_fresh، python_identity، uv_identity، target_os_arch_abi، artifact_inventory_hash، clean_environment، offline_result، failure_layer و residual_system_boundary. هر نتیجه را OBSERVED، INFERRED یا UNKNOWN برچسب بزن.
دو سؤال جدا داری: «آیا lock با metadata فعلی پروژه سازگار است؟» و «آیا همین target با شواهد محلی موجود میتواند محیط locked را از صفر بازسازی کند؟»
معنای فعلی رفتارهای uv در محدوده این درس
مستندات فعلی uv بین locking و synchronization تفاوت میگذارند. uv sync محیط پروژه را بهروز میکند و بهصورت پیشفرض exact sync است. پیش از sync پروژه دوباره lock میشود مگر --locked یا --frozen داده شود. --locked تازگی lock را بررسی میکند و بهجای تغییر فایل در حالت ناسازگار fail میشود؛ --frozen lock موجود را بدون بررسی تازگی metadata بهعنوان مرجع استفاده میکند. --offline شبکه را غیرفعال میکند و uv را به داده cacheشده و فایلهای محلی محدود میکند.
پس این flagها یک ادعا را ثابت نمیکنند. frozen میتواند عمداً metadata جدید را نادیده بگیرد و offline نیز اگر cache گرم باشد الزاماً کفایت wheelhouse را ثابت نمیکند. برای همین Lab هنگام اثبات artifact closure از cache ایزوله استفاده میکند.
wheelhouse هم target-scoped است. wheelهای دارای کد کامپایلشده معمولاً به OS، معماری، interpreter یا ABI وابستهاند. بنابراین target کنار inventory ثبت میشود.
مثال: lock کهنه و artifact حذفشده
Baseline: fixture به demo-dep==1.0.0 وابسته است، uv.lock به wheelhouse بستهشده اشاره میکند و clean uv sync --locked --offline با cache ایزوله موفق میشود.
Mutation تازگی: requirement را به demo-dep==2.0.0 تغییر بده ولی lock را regenerate نکن. uv sync --locked --offline نباید lock را بیصدا تغییر دهد و باید stale state را fail کند. --frozen سؤال دیگری را جواب میدهد چون تازگی را بررسی نمیکند.
Counterexample محیط گرم: baseline را sync کن، wheel را حذف کن و با همان .venv import بگیر؛ ممکن است سبز بماند. سپس .venv را حذف کن، cache تازه بساز و locked offline sync را تکرار کن. failure اکنون مرز artifact محلی را آشکار میکند.
چهار میانبُر پرخطا
«uv.lock یعنی Python و OS هم pin شدهاند.» اصلاح: interpreter و target را جدا ثبت کن.
«import موفق است، پس بازسازی ممکن است.» اصلاح: .venv را نابود کن و cache تمیز داشته باش.
«--frozen تازگی lock را ثابت میکند.» اصلاح: وقتی سؤال freshness است از semantics مربوط به locked/check استفاده کن.
«این wheelhouse همهجا کار میکند.» اصلاح: artifact inventory را به target matrix مشخص bind کن.
برای مهندس باتجربه: claim محیط را reviewable کن
در CI یا release engineering، target identity و artifact inventory را کنار hash فایل lock نگه دار. با تغییر نسخه Python، OS/architecture، metadata وابستگی یا نیاز native-extension، نتیجه قبلی فقط شواهد target قبلی است و ممکن است نیاز به regeneration داشته باشد. قبل از اعلام آمادگی برای محیط disconnected، clean offline probe ارزش زیادی دارد.
موفقیت install را به correctness برنامه تعمیم نده؛ این دو لایه شواهد جدا هستند.
بازسازی دقیق در برابر هزینه artifact
نگهداری artifact set جدا برای targetهای مختلف هزینه storage و build دارد، اما claim را قابل audit میکند. wheelهای pure-Python میتوانند اشتراک را بیشتر کنند، ولی وجود چند wheel عمومی به معنی universal بودن کل dependency graph نیست.
cache سرعت را بالا میبرد، اما اگر هویتش کنترل نشود ارزش اثباتی reconstruction test کمتر میشود. برای closure verification، cache عمداً خالی معمولاً از sync سریعتر ولی مبهم بهتر است.
Lab: بازسازی از مرز محلی تمیز
از TOL004-LAB1 استفاده کن. python setup_fixture.py یک working copy داخل همان Lab میسازد. python inspect_context.py هویت Python، uv، platform، مسیرها و hash artifactها را ثبت میکند. python run_uv_probe.py baseline clean locked offline sync را با cache ایزوله اجرا میکند و uv را با --python صریحاً به Python فراخواننده bind میکند؛ هویت interpreter انتخابشده داخل .venv را نیز نگه دار. سپس mutation مربوط به stale lock و missing artifact را جداگانه اجرا و بین آنها reset کن.
Fixture برای اجرا به شبکه نیاز ندارد. اگر uv در محیط موجود نیست، UV_UNAVAILABLE را ثبت کن و نتیجه sync را جعل نکن.
حداقل شواهد قابل دفاع
hash دقیق project و lock، هویت executableها، target tuple، hash استاندارد inventory (SHA-256 روی خطوط مرتبشده name<TAB>sha256<LF>)، clean-environment declaration، command/result آفلاین، پاسخ mutation و residual system boundary را نگه دار. لایههای failure حداقل باید LOCK_FRESHNESS، INTERPRETER_TARGET، LOCAL_ARTIFACT_AVAILABILITY، CLEAN_ENVIRONMENT، SYSTEM_RESIDUAL و UNKNOWN_OR_MULTIPLE را تفکیک کنند.
قویترین نتیجه سبز این درس محدود است: پروژه locked برای target ثبتشده، با شواهد محلی ثبتشده و تحت clean boundary ثبتشده قابل بازسازی بوده است. این نتیجه target دیگر یا correctness برنامه را ثابت نمیکند.
ارزیابی: تشخیص، تصمیم، اجرا و انتقال
AS1: .venv گرم بعد از حذف wheel هنوز import میکند. کوچکترین مرز اثباتنشده را مشخص کن.
AS2: تیم uv.lock و wheel directory دارد، اما هویت Python/target و clean reconstruction ندارد. برای Closure Record تصمیم ACCEPT، REJECT یا DEFER بده و residual risk را بنویس.
AS3: fixture محلی را اجرا کن، matrix را کامل کن و mutationهای stale-lock و missing-artifact را مستقل اجرا کن.
AS4: target به Python/platform دیگری تغییر کرده و یک artifact ناسازگار یا مفقود است. تعیین کن آیا closure قبلی معتبر میماند و چه چیزی باید regenerate شود.
مرز منبع و تازگی
ادعاهای وابسته به ابزار فقط به مستندات رسمی uv و pip که در 2026-09-08 بازبینی شدهاند محدودند. مستندات فعلی uv همچنان freshness lock را از frozen use جدا میکنند، exact sync و offline local/cache behavior را مستند میکنند؛ مستندات pip نیز wheelhouse را installation bundle معرفی میکنند و درباره وابستگی wheelهای کامپایلشده به OS/architecture هشدار میدهند.
تاریخ review بعدی Bible برابر 2026-10-17 است. با تغییر semantics دستورها یا compatibility rules، فقط لایه volatile source باید refresh شود؛ scope درس به container/OS closure گسترش پیدا نمیکند.
ارزیابی
پاسخنامهی این درس در بستهی آموزش وجود ندارد؛ خودت جواب بده و صادقانه علامت بزن. «نیاز به مرور» درس را به صف تکرار میفرستد.
AS1 diagnosis
AS2 decision
AS3 application
AS4 transfer
ملاکهای ارزیابی (rubric)
- Boundary correctness (critical): identify the smallest lock/interpreter/artifact/clean-environment boundary without expanding the claim.
- Evidence traceability (critical): every conclusion cites a file/hash/command/identity or remains UNKNOWN.
- Mutation robustness (critical): stale-lock and missing-artifact mutations change the conclusion appropriately.
- Transfer & residual risk: adapt to a changed target and state what remains unproven.
Machine checks validate structure; the final engineering decision remains human-reviewed.
منابع و تازگی
مطالعهٔ موارد (case studies)
فایلهای آزمایشگاه
python setup_fixture.py- با
python inspect_context.pyهویت launcher/tool و hash استاندارد inventory را ثبت کن. python run_uv_probe.py baselineرا اجرا کن و هر دو فیلدrequested_python_identityوselected_environment_python_identityرا نگه دار. probe با--python، uv را به Python فراخواننده bind میکند.- Reset کن؛
python mutate_fixture.py stale-lockو سپسpython run_uv_probe.py stale-locked. - Reset کن؛ baseline را اجرا کن، wheel را با
remove-wheelحذف کن،warm-importرا بگیر و سپسclean-after-removeرا اجرا کن.
شبکه لازم نیست. UV_UNAVAILABLE یعنی شواهد runtime موجود نیست و با exit code غیرصفر پایان مییابد؛ آن را PASS نکن. hash inventory برابر SHA-256 خطوط مرتبشده UTF-8 با قالب name<TAB>sha256<LF> است. import محیط گرم شواهد بازسازی نیست.
رسانه و اسلایدهای درس
فایلهای آموزشی (دانلود)