पायथन: सत्यापन योग्य निर्भरता विवरण और बिल्ड वातावरण विवरण को एक पुनरुत्पादनीय रिलीज़ अनुबंध के अलग-अलग हिस्सों के रूप में संग्रहीत करें
pyproject.toml के [project.dependencies] में रनटाइम निर्भरता और [build-system.requires] में बिल्ड आवश्यकताओं को स्टोर करें, फिर एक अलग रिक्वायरमेंट्स फ़ाइल में sha256 हैश के साथ सटीक संस्करणों को पिन करें ताकि बाइट-स्तर पर सत्यापन योग्य रिलीज़ अनुबंध बनाया जा सके।
इस पृष्ठ पर
मुख्य विचार
pyproject.toml के भीतर [project.dependencies] में रनटाइम निर्भरता और [build-system.requires] में बिल्ड-टाइम आवश्यकताओं को परिभाषित करें। सटीक संस्करणों को पिन करें और एक अलग रिक्वायरमेंट्स फ़ाइल में --hash=sha256 प्रविष्टियाँ जोड़ें ताकि एक सत्यापन योग्य, बाइट-स्तर पर पुनरुत्पादनीय रिलीज़ अनुबंध बनाया जा सके।
pyproject.toml में रनटाइम निर्भरताओं को बिल्ड-सिस्टम आवश्यकताओं से अलग करें
pyproject.toml विनिर्देश दो अलग-अलग निर्भरता परतों को परिभाषित करता है। [build-system] तालिका उन पायथन-स्तर की निर्भरताओं की घोषणा करती है जो प्रोजेक्ट के बिल्ड सिस्टम, जैसे कि setuptools या flit को चलाने के लिए आवश्यक होती हैं। उस तालिका के लिए requires कुंजी अनिवार्य है और बिल्ड-टाइम पैकेजों को सूचीबद्ध करती है। PEP 621 द्वारा पेश की गई [project] तालिका में dependencies कुंजी होती है, जो उन पैकेजों को सूचीबद्ध करती है जिनकी उपभोक्ताओं को इंस्टॉलेशन समय पर आवश्यकता होती है (रनटाइम निर्भरता)। इन्हें पैकेज मेटाडेटा में Requires-Dist प्रविष्टियों के रूप में मैप किया जाता है।
एक पुनरुत्पादनीय रिलीज़ अनुबंध के लिए इन परतों को अलग रखना आवश्यक है। समान वितरण आर्टिफैक्ट्स उत्पन्न करने के लिए बिल्ड वातावरण का पुनरुत्पादनीय होना चाहिए, जबकि इंस्टॉलेशन के बाद सुसंगत व्यवहार सुनिश्चित करने के लिए रनटाइम वातावरण का पुनरुत्पादनीय होना चाहिए। pyproject.toml में दोनों की घोषणा करके, आप अनुबंध को स्पष्ट और सत्यापन योग्य बनाते हैं: कोई भी यह निरीक्षण कर सकता है कि बिल्ड करने के लिए किन उपकरणों की आवश्यकता है और चलाने के लिए किन पुस्तकालयों की आवश्यकता है। विनिर्देश नोट करता है कि उपकरणों को [build-system] तालिका के अस्तित्व की आवश्यकता नहीं होनी चाहिए; यदि यह अनुपस्थित है, तो डिफॉल्ट का उपयोग किया जाता है, जो भिन्न हो सकते हैं। इसलिए, दोनों परतों को स्पष्ट रूप से बताने से अस्पष्टता समाप्त हो जाती है।
पिनिंग और हैश-चेकिंग अलग-अलग ट्रस्ट बाउंड्रीज़ को क्यों संबोधित करते हैं
रिक्वायरमेंट्स फ़ाइल में == के साथ पैकेज संस्करणों को पिन करना उन अपस्ट्रीम संस्करण परिवर्तनों से बचाता है जो बग या असंगतियां पैदा कर सकते हैं। हालांकि, यह अभी भी पैकेज इंडेक्स (जैसे PyPI) और TLS सर्टिफिकेट चेन पर भरोसा करता है। एक हमलावर जो इंडेक्स से समझौता करता है या मैन-इन-द-मिडल हमला करता है, वह उसी संस्करण संख्या वाला एक दुर्भावनापूर्ण पैकेज दे सकता है।
हैश-चेकिंग मोड, जिसे --require-hashes और --hash=sha256:... प्रविष्टियों के साथ सक्षम किया जाता है, डाउनलोड किए गए आर्टिफैक्ट को एक ज्ञात डाइजेस्ट के विरुद्ध बाइट-दर-बाइट सत्यापित करता है। यह इंडेक्स समझौते, सर्टिफिकेट चेन हमलों और बिना संस्करण वृद्धि के पैकेज के चुपचाप री-अपलोड (उन इंडेक्स पर जो इसकी अनुमति देते हैं) से बचाता है। pip दस्तावेज़ीकरण बताता है कि हैश-चेकिंग एक निजी इंडेक्स सर्वर चलाने का एक श्रम-बचत विकल्प है: यह पैकेजों को अपलोड करने, ACL बनाए रखने और ऑडिट ट्रेल रखने की आवश्यकता को समाप्त करता है, जबकि एक VCS रिक्वायरमेंट्स फ़ाइल के लिए वह ट्रेल प्रदान करता है। इसका ट्रेड-ऑफ रखरखाव लागत है: हर बार जब निर्भरता संस्करण बदलता है, तो हैश को पुनर्जीवित और समीक्षा किया जाना चाहिए। यह दृष्टिकोण स्वचालित सर्वर परिनियोजन के लिए उपयुक्त है जहाँ वातावरण नियंत्रित होता है।
ठोस उदाहरण: दोनों परतों वाला एक रिलीज़ अनुबंध
एक न्यूनतम pyproject.toml फ़ाइल build-system.requires (जैसे, setuptools और wheel) और project.dependencies (जैसे, requests और pydantic) को घोषित करती है। एक साथी requirements-pinned.txt फ़ाइल, जिसे pip-compile या pip freeze द्वारा जेनरेट किया गया है, हर ट्रांज़िटिव डिपेंडेंसी को सटीक वर्ज़न और sha256 हैश के साथ पिन करती है। ये दोनों फ़ाइलें मिलकर एक सत्यापन योग्य अनुबंध बनाती हैं।
इंस्टॉल करने के लिए, pip install --require-hashes -r requirements-pinned.txt चलाएँ। यह सुनिश्चित करता है कि डाउनलोड किया गया हर पैकेज रिकॉर्ड किए गए हैश से मेल खाता है। बिल्ड सिस्टम आवश्यकताओं का उपयोग तब किया जाता है जब प्रोजेक्ट को सोर्स से बिल्ड किया जाता है; यदि केवल एक प्री-बिल्ट व्हील इंस्टॉल किया जाता है, तो इंस्टॉलेशन के समय उनकी आवश्यकता नहीं होती है, लेकिन वे उन लोगों के लिए अनुबंध का हिस्सा होते हैं जिन्हें दोबारा बिल्ड करने की आवश्यकता है।
build-system.requires सूची यह सुनिश्चित करती है कि बिल्ड टूलिंग पुनरुत्पादनीय (reproducible) हो; project.dependencies यह घोषित करता है कि इंस्टॉल किए गए एप्लिकेशन को किसकी आवश्यकता है। साथी रिक्वायरमेंट्स फ़ाइल सटीक वर्ज़न पिन करती है और सभी ट्रांज़िटिव डिपेंडेंसी के लिए हैश प्रदान करती है, जो pip install --require-hashes -r requirements-pinned.txt के साथ उपयोग किए जाने पर सत्यापन योग्य रिलीज़ अनुबंध बनाती है। दिखाए गए हैश संक्षिप्त प्लेसहोल्डर हैं; वास्तविक हैश pip-compile या pip freeze के साथ जेनरेट किए जाने चाहिए और फिर मैन्युअल रूप से सत्यापित या वर्ज़न कंट्रोल में कमिट किए जाने चाहिए। चिंताओं के इस अलगाव का अर्थ है कि रनटाइम डिपेंडेंसी को अपडेट करने के लिए बिल्ड सिस्टम विनिर्देश को बदलने की आवश्यकता नहीं होती है, और इसके विपरीत भी। केवल pyproject.toml पुनरुत्पादनीयता लागू नहीं करता है; यह पिन की गई, हैश वाली रिक्वायरमेंट्स फ़ाइल के साथ संयोजन है जो अनुबंध बनाता है। build-system टेबल पुनरुत्पादनीयता के लिए अनिवार्य है क्योंकि यह बिल्ड टूल्स को पिन करती है; इसे छोड़ने पर टूल-विशिष्ट डिफॉल्ट्स पर निर्भर रहना होगा जो अलग-अलग वातावरणों में भिन्न हो सकते हैं, जिससे अनुबंध टूट सकता है।
# pyproject.toml
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "myapp"
version = "1.0.0"
dependencies = ["requests>=2.31", "pydantic>=2.5"]
# requirements-pinned.txt (generated by pip-compile or pip freeze)
requests==2.31.0 --hash=sha256:58cd2187c8b806c9970b3f8a8e7c1d2e4f6a8b9c0d1e2f3a4b5c6d7e8f9a0b1
pydantic==2.5.0 --hash=sha256:7f4f1b1b0d8d4e8c9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2
urllib3==2.1.0 --hash=sha256:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
annotated-types==0.6.0 --hash=sha256:b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3
pydantic-core==2.14.1 --hash=sha256:c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4
typing-extensions==4.9.0 --hash=sha256:d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5
# Install command enforcing hash verification:
pip install --require-hashes -r requirements-pinned.txtइस दृष्टिकोण की सीमाएं
कंपाइल किए गए व्हील्स वाले व्हीलहाउस बंडल OS और आर्किटेक्चर विशिष्ट होते हैं, इसलिए वे मशीनों के बीच पोर्टेबल नहीं होते हैं। हैश-चेकिंग पैकेज की उपलब्धता की गारंटी उस तरह से नहीं देती जैसे एक प्राइवेट इंडेक्स या वेंडर्ड लाइब्रेरी देती है; यदि किसी पैकेज को इंडेक्स से हटा दिया जाता है, तो इंस्टॉलेशन विफल हो जाता है भले ही हैश ज्ञात हो। [build-system] टेबल वैकल्पिक है; जब यह अनुपस्थित होती है, तो टूल्स डिफॉल्ट्स पर वापस चले जाते हैं, जो विभिन्न वातावरणों में भिन्न हो सकते हैं, जिससे पुनरुत्पादनीयता प्रभावित होती है। हैश के साथ पिनिंग अभी भी शुरुआती रिज़ॉल्यूशन पर भरोसा करती है और पिन किए गए वर्ज़न के अंदर मौजूद दुर्भावनापूर्ण कोड से सुरक्षा नहीं करती है। अंत में, हैश बनाए रखने से ओवरहेड बढ़ता है: हर डिपेंडेंसी अपडेट के लिए हैश प्रविष्टियों को फिर से जेनरेट और रिव्यू करने की आवश्यकता होती है।
उपयोग की शर्तें
- क्या आपका प्रोजेक्ट [build-system] और [project] दोनों तालिकाओं के साथ pyproject.toml का उपयोग करता है?
- क्या आप निर्भरता संस्करण बदलने पर हैश प्रविष्टियों को पुनर्जीवित करने के लिए तैयार हैं?
- क्या लक्ष्य वातावरण इतना समान है कि संकलित व्हील्स (यदि कोई हों) पोर्टेबल हैं, या क्या आप उन्हें प्रत्येक मशीन पर पुन: निर्माण कर सकते हैं?
- क्या आपके पास पिन की गई रिक्वायरमेंट्स फ़ाइल (जैसे, pip-compile या pip freeze) उत्पन्न करने और समीक्षा करने की प्रक्रिया है?
- क्या आप सुरक्षा पैच और अपग्रेड के लिए हैश अपडेट करने की रखरखाव लागत स्वीकार कर सकते हैं?
- क्या आपकी उपलब्धता आवश्यकताओं के लिए निजी इंडेक्स या वेंडर्ड लाइब्रेरी की अनुपस्थिति स्वीकार्य है?
उपयोग की सीमाएँ
संकलित व्हील्स वाले व्हीलहाउस बंडल OS और आर्किटेक्चर विशिष्ट होते हैं, इसलिए वे मशीनों के बीच पोर्टेबल नहीं होते हैं। हैश-चेकिंग पैकेज उपलब्धता की गारंटी उस तरह से नहीं देती जैसे कि एक निजी इंडेक्स या वेंडर्ड लाइब्रेरी देती। [build-system] तालिका वैकल्पिक है; अनुपस्थित होने पर, उपकरण डिफॉल्ट पर वापस चले जाते हैं, जो विभिन्न वातावरणों में भिन्न हो सकते हैं। हैश के साथ पिनिंग अभी भी प्रारंभिक रिज़ॉल्यूशन पर भरोसा करती है और पिन किए गए संस्करण के भीतर दुर्भावनापूर्ण कोड से सुरक्षा नहीं करती है।