PYTHONPATH متغيردليل تغليف بيثون الرسمي
الوحدة النمطية في Python عبارة عن ملف واحد (مع امتداد .py ) يحتوي على رمز Python. يتكون عادة من الفئات والوظائف والمتغيرات التي يمكن استخدامها بواسطة رمز Python الآخر. يتم استخدام الوحدات النمطية لتنظيم التعليمات البرمجية في وحدات منطقية وتسهيل إعادة استخدام الكود.
على سبيل المثال ، ضع في اعتبارك وحدة نمطية تسمى math_operations.py تحتوي على وظائف لأداء العمليات الرياضية مثل الإضافة والطرح والضرب وما إلى ذلك. يمكنك استيراد هذه الوظائف واستخدامها في البرامج النصية الأخرى للبيثون.
# math_operations.py
def add ( x , y ):
return x + y
def subtract ( x , y ):
return x - y حزمة في Python هي مجموعة من الوحدات التي تم تجميعها معًا في دليل. عادةً ما يتم تمثيل الحزمة بواسطة دليل يحتوي على ملف __init__.py (والذي يمكن أن يكون فارغًا) ووحدات بيثون واحدة أو أكثر. يشير ملف __init__.py إلى Python أنه ينبغي التعامل مع الدليل كحزمة.
على سبيل المثال ، فكر في حزمة تسمى my_package :
my_package/
├── __init__.py
├── module1.py
└── module2.py
هنا ، my_package عبارة عن حزمة تحتوي على module1.py و module2.py ، والتي يمكن استيرادها باستخدام تدوين DOT ( my_package.module1 ، my_package.module2 ).
الحزمة الفرعية في Python هي حزمة متداخلة داخل حزمة أخرى. هذا يعني أن الحزمة يمكن أن تحتوي على حزم أخرى وكذلك الوحدات النمطية. يتم إنشاء الحزم الفرعية عن طريق تنظيم الدلائل وإضافة ملفات __init__.py بشكل مناسب لتحديد بنية الحزمة.
على سبيل المثال:
my_parent_package/
├── __init__.py
└── my_sub_package/
├── __init__.py
├── module3.py
└── module4.py
في هذا الهيكل ، my_sub_package عبارة عن حزمة فرعية لـ my_parent_package ، ويمكن أن تحتوي على وحداتها الخاصة ( module3.py ، module4.py ). يمكن استيراد الحزمة الفرعية باستخدام ترميز DOT ( my_parent_package.my_sub_package.module3 ).
تشير حزمة التوزيع (أو التوزيع ببساطة) في Python إلى مجموعة معبأة من رمز Python والموارد التي يتم توفيرها للتثبيت. ويتضمن عادة الوحدات النمطية والحزم وملفات البيانات وملفات التكوين والموارد الأخرى اللازمة لغرض محدد (على سبيل المثال ، مكتبة أو تطبيق).
غالبًا ما يتم توزيع حزم التوزيع وتثبيتها باستخدام مديري حزم Python مثل pip ويمكن تحميلها على مستودعات الحزم مثل PYPI (فهرس حزمة Python) لسهولة التوزيع والتركيب من قبل المطورين الآخرين.
على سبيل المثال ، تشمل حزم التوزيع الشائعة numpy و fast-api و pandas ، وما إلى ذلك ، والتي يتم تثبيتها باستخدام pip وتوفر وظائف يمكن استخدامها في مشاريع Python.
sdistsetup.pypython setup.py build sdist لبناء توزيع المصدرpip install ./dist/<package_name>.tar.gz لتثبيت الحزمةpip list لمعرفة ما إذا كانت الحزمة مثبتة. إذا تم إجراء تغييرات في الحزمة ، فاستخدم pip install . والتي ستقوم ببناء وتثبيت أحدث حزمة على الطيران.
أو ببساطة استخدام قابلة للتحرير بحيث لا تضطر دائمًا إلى إعادة بناء حزمة Evrerytime تغييرات جديدة:
pip install --editable . sdist قصير لتوزيع المصدر ، ملف .tar يحتوي على رمزنا يسمى "SDIST". ما يعنيه ذلك هو أن حزمة التوزيع تحتوي فقط على مجموعة فرعية من رمز المصدر الخاص بنا.
"توزيع المصدر" هو في الأساس مجلد مضغوط يحتوي على رمز المصدر الخاص بنا.
wheel توزيع المصدر ( sdist ) :
*.py ) وملفات التكوين والأصول الأخرى المتعلقة بالمشروع.python setup.py sdist . عجلات ( bdist_wheel ) :
sdist ..whl .python setup.py bdist_wheel . تركيب أسرع :
*.whl ) أسرع من التثبيت من توزيعات المصدر ( *.tar.gz ).سهولة الاستخدام للمستخدمين :
sdist و bdist_wheelsdist و bdist_wheel لحزم بيثون لاستيعاب حالات الاستخدام المختلفة والمنصات.python setup.py sdist bdist_wheelمتطلبات التجميع :
لسوء الحظ ، يصبح إنشاء عجلات لجميع أنظمة التشغيل أمرًا صعبًا إذا كان لديك خطوة تجميع مطلوبة ، لذلك يقوم بعض المحطين OSS فقط ببناء عجلات لنظام تشغيل واحد.
pip فعليًا بتنفيذ setup.py (أو الملفات المكافئة) على جهازك ، مباشرة بعد تنزيل SDIST.قد يتطلب بناء العجلة رمز التجميع
gcc إذا كان رمز المصدر في C ، لكن اللغات الأخرى تتطلب مجمعاتها الخاصة. يجب على المستخدم تثبيتها على جهاز On On أو pip install ... سيفشل ببساطة. يمكن أن يحدث هذا عند تثبيت numpy ، pandas ، scipy ، pytorch ، tensorflow ، إلخ. قد يحتوي setup.py على رمز تعسفي. هذا غير آمن للغاية. قد يحتوي setup.py على رمز ضار.
إدارة التبعية :
gcc ، وما إلى ذلك) لتثبيت الحزم التي تتطلب تجميعًا بنجاح.المخاوف الأمنية :
setup.py لتثبيت الحزمة غير آمن لأنه ينفذ رمزًا تعسفيًا.wheelيتم تقسيم اسم ملف العجلات إلى أجزاء مفصولة بالوصلة:
{dist}-{version}(-{build})?-{python}-{abi}-{platform}.whl كل قسم في {brackets} هو علامة ، أو مكون من اسم العجلة الذي يحمل بعض المعنى حول ما تحتوي عليه العجلة وأين ستعمل العجلة أو لن تعمل.
على سبيل المثال: dist/packaging-0.0.0-py3-none-any.whl
packaging هو اسم الحزمة0.0.0 هو رقم Verisonpy3 إلى أنه بناء لبيثون 3abi . ABI تعني الواجهة الثنائية للتطبيق.any موقف لهذا الحزمة هي بناء للعمل على أي منصة.أمثلة أخرى:
cryptography-2.9.2-cp35-abi3-macosx_10_9_x86_64.whlchardet-3.0.4-py2.py3-none-any.whlPyYAML-5.3.1-cp38-cp38-win_amd64.whlnumpy-1.18.4-cp38-cp38-win32.whlscipy-1.4.1-cp36-cp36m-macosx_10_6_intel.whlوالسبب في ذلك هو أن ملف العجلات يحتوي على الكود الثنائي المسبق مسبقًا والذي يساعد على تثبيت الحزمة بسرعة.
صيانة الحزمة :
sdist و bdist_wheel لزيادة توافق وسهولة الاستخدام للمستخدمين إلى الحد الأقصى.النظر في تجربة المستخدم :
build أداة CLI و pyproject.toml"بناء التبعيات" هي أي شيء يجب تثبيته على نظامك من أجل إنشاء حزمة التوزيع الخاصة بك في SDIST أو عجلة.
على سبيل المثال ، كنا بحاجة إلى pip install wheel من أجل تشغيل python setup.py bdist_wheel بحيث تكون wheel بمثابة تبعية لبناء عجلات.
يمكن أن تحصل ملفات setup.py على التعقيد.
قد تحتاج إلى pip install ... المكتبات الخارجية واستيرادها إلى ملف setup.py الخاص بك لاستيعاب عمليات البناء المعقدة.
تُظهر المحاضرة pytorch وتدفق airflow كأمثلة على الحزم مع ملفات setup.py المعقدة.
بطريقة ما ، يجب أن تكون قادرًا على توثيق تبعيات بناء خارج setup.py .
إذا تم توثيقها في ملف setup.py ... فلن تتمكن من تنفيذ ملف setup.py لقراءة التبعيات الموثقة (مثل إذا تم تحديدها في list في مكان ما في الملف).
هذه هي المشكلة الأصلية pyproject.toml كان من المفترض حلها.
# pyproject.toml
[ build-system ]
# Minimum requirements for the build system to execute.
requires = [ " setuptools>=62.0.0 " , " wheel " ] pyproject.toml يجلس بجوار setup.py في شجرة الملفات
يعد build CLI Tool ( pip install build ) مشروعًا خاصًا من قبل هيئة التغليف Python (PYPA) التي
[build-system] في pyproject.toml ،pip install build
# both setup.py and pypproject.toml should be together, ideally in the root directory
# python -m build --sdist --wheel path/to/dir/with/setup.py/and/pyproject.toml
python -m build --sdist --wheel . setup.py إلى ملف config setup.cfgالانتقال من
# setup.py
from pathlib import Path
from setuptools import find_packages , setup
import wheel
# Function to read the contents of README.md
def read_file ( filename : str ) -> str :
filepath = Path ( __file__ ). resolve (). parent / filename
with open ( filepath , encoding = "utf-8" ) as file :
return file . read ()
setup (
name = "packaging-demo" ,
version = "0.0.0" ,
packages = find_packages (),
# package meta-data
author = "Amit Vikram Raj" ,
author_email = "[email protected]" ,
description = "Demo for Python Packaging" ,
license = "MIT" ,
# Set the long description from README.md
long_description = read_file ( "README.md" ),
long_description_content_type = "text/markdown" ,
# install requires: libraries that are needed for the package to work
install_requires = [
"numpy" , # our package depends on numpy
],
# setup requires: the libraries that are needed to setup/build
# the package distribution
# setup_requires=[
# "wheel", # to build the binary distribution we need wheel package
# ],
)ل
# setup.py
from setuptools import setup
# Now setup.py takes it's configurations from setup.cfg file
setup () # setup.cfg
[metadata]
name = packaging-demo
version = attr: packaging_demo.VERSION
author = Amit Vikram Raj
author_email = [email protected]
description = Demo for Python Packaging
long_description = file: README.md
keywords = one, two
license = MIT
classifiers =
Framework :: Django
Programming Language :: Python :: 3
[options]
zip_safe = False
include_package_data = True
# same as find_packages() in setup()
packages = find:
python_requires = >=3.8
install_requires =
numpy
importlib-metadata ; python_version<"3.10"كما يتم تمرير إعداد الإضافات إلى ملف
pyproject.toml. لقد حددنا هناbuild-systemمشابه لـsetup_requiresفيsetup.py
# pyproject.toml
[ build-system ]
# Minimum requirements for the build system to execute
requires = [ " setuptools " , " wheel " , " numpy<1.24.3 " ]
# Adding ruff.toml to pyproject.toml
[ tool . ruff ]
line-length = 99
[ tool . ruff . lint ]
# 1. Enable flake8-bugbear (`B`) rules, in addition to the defaults.
select = [ " E " , " F " , " B " , " ERA " ]
# 2. Avoid enforcing line-length violations (`E501`)
ignore = [ " E501 " ]
# 3. Avoid trying to fix flake8-bugbear (`B`) violations.
unfixable = [ " B " ]
# 4. Ignore `E402` (import violations) in all `__init__.py` files, and in select subdirectories.
[ tool . ruff . lint . per-file-ignores ]
"__init__.py" = [ " E402 " ]
"**/{tests,docs,tools}/*" = [ " E402 " ]
# copying isort configurations from .isort.cfg to pyproject.toml
[ tool . isort ]
profile = " black "
multi_line_output = " VERTICAL_HANGING_INDENT "
force_grid_wrap = 2
line_length = 99
# copying balck config from .black.toml to pyproject.toml
[ tool . black ]
line-length = 99
exclude = " .venv "
# copying flake8 config from .flake8 to pyproject.toml
[ tool . flake8 ]
docstring-convention = " all "
extend-ignore = [ " D107 " , " D212 " , " E501 " , " W503 " , " W605 " , " D203 " , " D100 " ,
" E305 " , " E701 " , " DAR101 " , " DAR201 " ]
exclude = [ " .venv " ]
max-line-length = 99
# radon
radon-max-cc = 10
# copying pylint config from .pylintrc to pyproject.toml
[ tool . pylint . "messages control" ]
disable = [
" line-too-long " ,
" trailing-whitespace " ,
" missing-function-docstring " ,
" consider-using-f-string " ,
" import-error " ,
" too-few-public-methods " ,
" redefined-outer-name " ,
] لقد تم التعامل مع setup.py كملف تكوين مجيد ، وليس الاستفادة حقًا من حقيقة أنه ملف Python عن طريق إضافة منطق إليه.
هذا هو أكثر شيوعا من غير. أيضًا ، كان هناك تحول عام بعيدًا عن استخدام Python لملفات التكوين لأن القيام بذلك يضيف التعقيد إلى استخدام ملفات التكوين (مثل الاضطرار إلى تثبيت المكتبات لتنفيذ ملف التكوين).
setup.cfg هو ملف مصاحب إلى setup.py يسمح لنا بتحديد تكوين الحزمة لدينا في ملف نصي ثابت - على وجه التحديد ملف تنسيق INI.
سيتم البحث عن أي قيم لا نمررها مباشرة كوسائط إلى الإعداد () من خلال الاحتجاج () SETUP () في ملف SETUP.CFG ، والذي يهدف إلى الجلوس المجاور لـ SETUP.PY في شجرة الملف إذا تم استخدامه.
الآن نحن نتراكم الكثير من الملفات!
setup.pysetup.cfgpyproject.tomlREADME.md.pylintrc ، .flake8 ، .blackrc ، ruff.toml ، .mypy ، pre-commit-config.yaml إلخ ، إلخ.CHANGELOG أو CHANGELOG.mdVERSION أو version.txt اتضح أنه يمكن استبدال جميع هذه الملفات تقريبًا بـ pyproject.toml . pyproject.toml كل أداة جودة الرمز / الكود تقريبًا تحليل قسم يسمى [tool.black] [tool.<name>]
يجب أن تخبرك مستندات كل أداة فردية بكيفية تحقيق ذلك.
أعلاه هو pyproject.toml مع تكوينات للعديد من أدوات linting التي استخدمناها في الدورة.
هل يمكن استبدال
setup.cfgوsetup.pyأيضًا؟
setup.cfg إلى pyproject.tomlمن
setup.cfg
# setup.cfg
[metadata]
name = packaging-demo
version = attr: packaging_demo.VERSION
author = Amit Vikram Raj
author_email = [email protected]
description = Demo for Python Packaging
long_description = file: README.md
keywords = one, two
license = MIT
classifiers =
Programming Language :: Python :: 3
[options]
zip_safe = False
include_package_data = True
# same as find_packages() in setup()
packages = find:
python_requires = >=3.8
install_requires =
numpy
importlib-metadata ; python_version<"3.10"ل
# pyproject.toml
[ build-system ]
# Minimum requirements for the build system to execute
requires = [ " setuptools>=61.0.0 " , " wheel " ]
# Adding these from setup.cfg in pyproject.toml file
[ project ]
name = " packaging-demo "
authors = [{ name = " Amit Vikram Raj " , email = " [email protected] " }]
description = " Demo for Python Packaging "
readme = " README.md "
requires-python = " >=3.8 "
keywords = [ " one " , " two " ]
license = { text = " MIT " }
classifiers = [ " Programming Language :: Python :: 3 " ]
dependencies = [ " numpy " , ' importlib-metadata; python_version<"3.10" ' ]
dynamic = [ " version " ]
# version = "0.0.3"
# https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html#dynamic-metadata
[ tool . setuptools . dynamic ]
# every while making changes in package, you can change the verison in one of these files
# version = {attr = "packaging_demo.VERSION"} # version read by 'packaging_demo/__init__.py' file
version = { file = [ " version.txt " ]} # version read by 'version.txt' file in root folder
python -m build --sdist --wheel .- يعمل بشكل مثالي ، لقد تخلصنا من ملف تكوين آخر (setup.cfg)
setup.py مع build-backend أضاف PEP 517 وسيطة build-backend إلى pyproject.toml مثل ذلك:
[ build-system ]
# Defined by PEP 518:
requires = [ " flit " ]
# Defined by this PEP:
build-backend = " flit.api:main " # The above toml config is equivalent to
import flit . api
backend = flit . api . main يحدد build-backend نقطة دخول (وحدة بيثون قابلة للتنفيذ في هذه الحالة) بأن build يستخدم CLI للقيام بالفعل بعمل تحليل pyproject.toml وبناء العجلة و SDIST.
هذا يعني أنه يمكنك تنفيذ الواجهة الخلفية الخاصة بك اليوم عن طريق كتابة برنامج يقوم بذلك ، ويمكنك استخدامه عن طريق إضافة الحزمة الخاصة بك إلى requires = [...] تحديد نقطة الإدخال في build-backend = ...
إذا لم تقم بتحديد build-backend في pyproject.toml ، فمن المفترض أن يكون setuptools وسيحصل الحزمة بشكل جيد.
setup.py وقمنا بتشغيل python -m build --sdist --wheel . يتم تشغيله بشكل مثالي بدونها لأن القيمة الافتراضية لنظام build-system يتم تعيينها على أنها build-backend = "setuptools.build_meta" في build CLI التي تبني حزمةنا. ولكن لا يزال بإمكانك إعلان setuptools صراحةً كأجهزة خلفية مثل هذا
# pyproject.toml
...
[ build-system ]
requires = [ " setuptools>=61.0.0 " , " wheel " ]
build-backend = " setuptools.build_meta "
... عادة ما يمتد كل الواجهة الخلفية للبناء إلى ملف pyproject.toml مع خيارات التكوين الخاصة به. على سبيل المثال،
# pyproject.toml
...
[ tool . setuptools . package-data ]
package_demo = [ " *.json " ]
[ tool . setuptools . dynamic ]
version = { file = " version.txt " }
long_description = { file = " README.md " }
... إذا اخترت استخدام setuptools في مشروعك ، فيمكنك إضافة هذه الأقسام إلى pyproject.toml . يمكنك قراءة المزيد حول هذا الموضوع في وثائق setuptools
غالبًا ما يكون من المفيد تضمين ملفات غير بايثون مثل ملفات البيانات أو الملفات الثنائية داخل الحزمة الخاصة بك نظرًا لأن رمز Python الخاص بك يعتمد على هذه الملفات غير البايثون.
ثم رأينا أنه إذا كنا سنقوم بتضمين هذه الملفات ، فنحن بحاجة إلى الحصول على هذه الملفات لتنتهي داخل مجلد الحزمة لدينا لأنه مجلد الحزمة الخاص بنا الذي ينتهي داخل بيئات المستخدمين الافتراضية عند التثبيت.
لقد رأينا أيضًا ذلك افتراضيًا ، أن جميع الملفات غير البايثون لا تجعلها في مجلد البيئة الافتراضي النهائي. وهذا هو ، لا تجعله في مجلد الحزمة لدينا أثناء إجراء البناء.
لذا ، كيف نتأكد من أن هذه الملفات تنتهي في بنية العجلة/DIST الخاصة بنا؟ على سبيل المثال هنا ، نقوم بتجريبي مع ملف cities.json الذي نريده في الحزمة الخاصة بنا كما هو مستخدم بواسطة ملف states_info.py .
مستندات
setuptoolsالرسمية لدعم البيانات
# pyprject.toml
[ tool . setuptools ]
# ...
# By default, include-package-data is true in pyproject.toml, so you do
# NOT have to specify this line.
include-package-data = true لذلك ، فإن Setuptools افتراضيًا قد include-package-data التي تم تعيينها إلى true كما هو موضح في المستندات الرسمية ، لكننا نحتاج إلى إنشاء ملف إضافي MANIFEST.in
IMP: إنه يستورد جميع المجلدات الموجودة في دليل الحزمة
__init__.pyالتي تغرس دليل البيانات الذي نريد تضمينه لأن عمليةfind_packages()التي لا تُحصل__init__.pysetuptools
# MANIFEST.in
include packaging_demo/*.json
include packaging_demo/my_folder/*.json
OR
Recursive include all json files in the package directory
recursive-include packaging_demo/ *.json
مستندات على تكوين ملف manesest.in
MANIFEST.in من مستندات setuptools ، يمكننا إضافة هذا في ملف pyproject.toml الخاص بنا:
# this is by default true so no need to explicitly add it
# but as mentioned in the docs, it is false for other methods like setup.py or setup.cfg
[ tool . setuptools ]
include-package-data = true
# add the data here, it's finding the files recursively
[ tool . setuptools . package-data ]
package_demo = [ " *.json " ]build-backend الأخرى من setuptools بخلاف setuptools ، يمكننا استخدام أنظمة البناء الخلفية هذه. النقطة التي يجب ملاحظتها هي عند استخدام أنظمة أخرى ، يجب أن تتبع cofiguration pyproject.toml .
فتحة
[ build-system ]
requires = [ " hatchling " ]
build-backend = " hatchling.build "شِعر
[ build-system ]
requires = [ " poetry-core>=1.0.0 " ]
build-backend = " poetry.core.masonry.api " توثيق الإصدارات الدقيقة من تبعياتنا وتبعياتها وما إلى ذلك.
من المستحسن أن يكون هناك أقل عدد ممكن من التبعيات المرتبطة بحزمنا ، حيث يمكن أن يؤدي إلى الجحيم التبعية ، أو تعارض التبعية مع الحزمة الأخرى كما هو موضح في المحاضرات.
كلما زادت شجرة التبعية أكثر تعقيدًا فرصة التعارض مع النسخة المستقبلية من المكتبات الأخرى.
تحليل الرسم البياني التبعية بواسطة إريك
إن الحفاظ على الإصدارات المثبتة من التبعيات وإصدارات Python أمر أساسي لأغراض استكشاف الأخطاء وإصلاحها:
pip freeze > requirements.txt pip install pipdeptree graphviz
sudo apt-get install graphviz
# generate the dependency graph
pipdeptree -p packaging-demo --graph-output png > dependency-graph.png[ project . optional-dependencies ]
dev = [ " ruff " , " mypy " , " black " ] # installing our package with optional dependencies
pip install ' .[dev] ' [ project . optional-dependencies ]
# for developement
dev = [ " ruff " , " mypy " , " black " ]
# plugin based architecture
colors = [ " rich " ] # plugin based installation
pip install ' .[colors] '
# here we demo with rich library, if user wants the output to be
# colorized then they can install our package like this.
# we can add multiple optional dependencies like:
pip install ' .[colors, dev] ' [ project . optional-dependencies ]
# for developement
dev = [ " ruff " , " mypy " , " black " ]
# plugin based architecture
colors = [ " rich " ]
# install all dependencies
all = [ " packaging-demo[dev, colors] " ] # Installing all dependencies all at once
pip install ' .[all] ' يمكننا استخدام Snyk للتحقق من مدى استقرار ودعم جيد ، إذا كانت أي مشكلات أمان ، وما إلى ذلك موجودة لتبعيات سنستخدمها في حزمةنا ثم اتخاذ القرار بشأن استخدامه في مشروعنا.
لتوضيح حزمةنا إلى Pypi [مؤشر تغليف Python] ، كما هو مذكور في الدليل الرسمي ، نستخدم twine CLI Tool.
pip install twine
twine upload --helpقم بإنشاء رمز API لاختبار PYPI أو PYPI Prod
قم ببناء حزمة Python الخاصة بك: python -m build --sdist --wheel "${PACKAGE_DIR}" ، هنا نقوم ببناء كل من SDIST والعجلة ، على النحو الموصى به.
قم بتشغيل أداة Twine: twine upload --repository testpypi ./dist/* ، uplading to test-pypi
CMake و Makefile
sudo apt-get install makeTaskFile
justfile
بينفوك
ديف
$ rightarrow $ QA/التدريج$ rightarrow $ همز



# .github/workflows/publish.yaml
name : Build, Test, and Publish
# triggers: whenever there is new changes pulled/pushed on this
# repo under given conditions, run the below jobs
on :
pull_request :
types : [opened, synchronize]
push :
branches :
- main
# Manually trigger a workflow
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch
workflow_dispatch :
jobs :
build-test-and-publish :
runs-on : ubuntu-latest
steps :
# github actions checksout, clones our repo, and checks out the branch we're working in
- uses : actions/checkout@v3
with :
# Number of commits to fetch. 0 indicates all history for all branches and tags
# fetching all tags so to aviod duplicate version tagging in 'Tag with the Release Version'
fetch-depth : 0
- name : Set up Python 3.8
uses : actions/setup-python@v3
with :
python-version : 3.8
# tagging the release version to avoid duplicate releases
- name : Tag with the Release Version
run : |
git tag $(cat version.txt)
- name : Install Python Dependencies
run : |
/bin/bash -x run.sh install
- name : Lint, Format, and Other Static Code Quality Check
run : |
/bin/bash -x run.sh lint:ci
- name : Build Python Package
run : |
/bin/bash -x run.sh build
- name : Publish to Test PyPI
# setting -x in below publish:test will not leak any secrets as they are masked in github
if : ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
run : |
/bin/bash -x run.sh publish:test
env :
TEST_PYPI_TOKEN : ${{ secrets.TEST_PYPI_TOKEN }}
- name : Publish to Prod PyPI
if : ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
run : |
/bin/bash -x run.sh publish:prod
env :
PROD_PYPI_TOKEN : ${{ secrets.PROD_PYPI_TOKEN }}
- name : Push Tags
if : ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
run : |
git push origin --tagsمتطلبات القفل
التبعية التخزين المؤقت
عندما يتم تنفيذ إجراءات GitHub في Github CI ، في كل مرة يتم تشغيلها على حاوية جديدة. وبالتالي ، في كل مرة سيتعين علينا تنزيل التبعيات وإعادة تثبيتها من PIP مرارًا وتكرارًا ؛ وهو ليس جيدًا لأنه لا ينطبق على سير العمل الخاص بنا.
وبالتالي ، نريد تثبيت جميع التبعيات عندما يعمل سير العمل أولاً واستخدامه في كل مرة يتم فيها تشغيل تدفق جديد.
توفر إجراءات GitHub هذه الوظيفة من خلال تخزين التبعيات ، وهي تخزن التبعيات المثبتة ( ~/.cache/pip ) وتنزيلها في كل مرة يتم تشغيل سير عمل جديد. مستندات
- uses : actions/cache@v3
with :
path : ~/.cache/pip
key : ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys : |
${{ runner.os }}-pip-setup-python جيثب steps :
- uses : actions/checkout@v4
- uses : actions/setup-python@v5
with :
python-version : ' 3.9 '
cache : ' pip ' # caching pip dependencies
- run : pip install -r requirements.txtالتوازي
# See .github/workflows/publish.yaml
jobs :
check-verison-txt :
...
lint-format-and-static-code-checks :
....
build-wheel-and-sdist :
...
publish :
needs :
- check-verison-txt
- lint-format-and-static-code-checks
- build-wheel-and-sdist
...