Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 660 – pyproject.toml 기반 빌드(휠 기반)의 편집 가능 설치

Author:
Daniel Holth <dholth at gmail.com>, Stéphane Bidoul <stephane.bidoul at gmail.com>
Sponsor:
Paul Moore <p.f.moore at gmail.com>
Discussions-To:
Discourse thread
Status:
Final
Type:
Standards Track
Topic:
Packaging
Created:
30-Mar-2021
Post-History:

Resolution:
Discourse thread

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

초록

이 문서는 편집 가능 모드에서 패키지를 설치하기 위한 PEP 517 스타일의 방법을 설명합니다.

동기

Python 프로그래머는 예를 들어 소스 저장소의 체크아웃에서 작업하는 방식으로, 패키지를 site-packages에 설치(즉, 복사)하지 않고도 패키지를 개발할 수 있기를 원합니다.

관련 소스 디렉터리를 PYTHONPATH에 추가하여 이를 수행할 수도 있지만, setuptools는 이 과정을 더 쉽게 만드는 setup.py develop 메커니즘을 제공하며 콘솔 스크립트와 같은 종속성과 진입점도 설치합니다. pippip install --editable 옵션을 통해 이 메커니즘을 노출합니다.

가져온 Python 코드가 소스 디렉터리에 남아 있도록 프로젝트를 설치하는 방식을 editable 설치 모드라고 합니다.

이제 PEP 517가 setuptools의 대안을 만들고 설치 프론트엔드와 빌드 백엔드를 분리하는 메커니즘을 제공하므로, 패키지를 편집 가능 모드로 설치하기 위한 새로운 메커니즘이 필요합니다.

근거

PEP 517는 “Editable installs”를 연기했으며, 이는 setup.py 이외의 배포판에는 해당 기능이 없었다는 의미입니다. 이러한 배포판에서 editable 설치를 유지할 수 있는 유일한 방법은 호환 가능한 setup.py develop 구현을 제공하는 것이었습니다. 편집 가능 훅을 정의하면 다른 빌드 프론트엔드도 setup.py와 동등한 기능을 갖게 됩니다.

용어 및 목표

편집 가능 설치 모드는 설치되는 프로젝트의 소스 코드가 로컬 디렉터리에서 사용 가능하다는 것을 의미합니다.

프로젝트가 편집 가능 모드로 설치되면, 사용자는 로컬 소스 트리의 프로젝트 python 코드 변경 사항이 새로운 설치 단계 없이 적용되기를 기대합니다.

진입점의 추가 또는 수정이나 새로운 종속성의 추가와 같은 일부 변경 사항은 적용되려면 새로운 설치 단계가 필요합니다. 이러한 변경 사항은 일반적으로 빌드 백엔드 구성 파일(예: pyproject.toml)에서 이루어지므로, python 소스 코드를 소스 트리에서 가져온다는 일반적인 사용자 기대와 일치합니다.

C 확장 모듈과 같은 비(非)-python 소스 코드의 수정 사항은 적용되려면 당연히 컴파일 및/또는 설치 단계가 필요합니다. 수행할 정확한 단계는 사용되는 빌드 백엔드에 따라 달라집니다.

프로젝트가 편집 가능 모드로 설치되면, 사용자는 설치가 일반 설치와 동일하게 동작하기를 기대합니다. 특히 코드는 다른 코드에서 가져올 수 있어야 하며, 메타데이터는 importlib.metadata와 같은 표준 메커니즘에서 사용할 수 있어야 합니다.

빌드 백엔드가 이 사양을 구현하는 방식에 따라, 일반 설치에는 포함되지 않을 소스 트리의 추가 파일이 존재하는 것과 같은 일부 사소한 차이가 나타날 수 있습니다. 빌드 백엔드는 이러한 잠재적 차이를 문서화하는 것이 좋습니다.

메커니즘

이 PEP는 PEP 517 백엔드 인터페이스에 세 개의 선택적 훅을 추가합니다. 이러한 훅은 설치되었을 때 해당 배포판을 소스 폴더에서 가져올 수 있도록 하는 휠을 빌드하는 데 사용됩니다.

build_editable

def build_editable(wheel_directory, config_settings=None, metadata_directory=None):
    ...

.whl 파일을 빌드하여 지정된 wheel_directory에 배치해야 합니다. 생성한 .whl 파일의 전체 경로가 아닌 기본 이름을 유니코드 문자열로 반환해야 합니다.

확장 모듈이나 기타 빌드 산출물을 사용할 수 있도록 배포판을 제자리에서 빌드하는 작업을 부수 효과로 수행할 수 있습니다.

파일(.whl)은 Wheel 바이너리 파일 형식 사양(PEP 427)을 준수해야 합니다. 특히 호환되는 .dist-info 디렉터리를 포함해야 합니다. 메타데이터는 build_wheel 또는 prepare_metadata_for_build_wheel이 생성했을 메타데이터와 동일해야 합니다. 단, 아래에서 설명하는 것처럼 Requires-Dist는 약간 다를 수 있습니다.

빌드 백엔드는 build_wheel 훅으로 생성된 휠과 동일한 의존성(Requires-Dist 메타데이터)을 가진 휠을 생성해야 합니다. 단, 런타임에 편집 가능 메커니즘이 작동하는 데 필요한 의존성(예: editables)은 추가할 수 있습니다.

“editable” 휠의 파일 이름도 PEP 427을 준수해야 합니다. build_wheel과 동일한 태그를 사용할 필요는 없지만, 시스템과 호환되는 것으로 태그되어야 합니다.

빌드 프런트엔드가 이전에 prepare_metadata_for_build_editable을 호출했고, 이 호출의 결과로 생성되는 휠의 메타데이터가 이전 호출과 일치해야 한다면, 생성된 .dist-info 디렉터리의 경로를 metadata_directory인자로 제공해야 합니다. 이 인자가 제공되면 build_editable은 동일한 메타데이터를 가진 휠을 반드시 생성해야 합니다. 빌드 프런트엔드가 전달한 디렉터리는 prepare_metadata_for_build_editable이 생성한 디렉터리와 반드시 동일해야 하며, 여기에는 해당 훅이 생성한 인식되지 않은 파일도 포함됩니다.

“editable” 휠은 배포를 위해서가 아니라 빌드 시스템과 프런트엔드 간의 일시적인 통신 수단으로 휠 형식을 사용합니다. 이를 통해 빌드 백엔드가 아무것도 직접 설치하지 않아도 됩니다. 이 휠은 최종 사용자에게 노출되거나 캐시되거나 배포되어서는 안 됩니다.

get_requires_for_build_editable

def get_requires_for_build_editable(config_settings=None):
    ...

이 훅은 pyproject.toml 파일에 지정된 것에 더해, build_editable 훅을 호출할 때 설치해야 하는 PEP 508 의존성 사양을 포함하는 문자열의 추가 목록을 반드시 반환해야 합니다.

정의되지 않은 경우 기본 구현은 return []과 동일합니다.

prepare_metadata_for_build_editable

def prepare_metadata_for_build_editable(metadata_directory, config_settings=None):
    ...

지정된 metadata_directory내부에 휠 메타데이터를 포함하는 .dist-info 디렉터리를 생성해야 합니다(즉, {metadata_directory}/{package}-{version}.dist-info/와 같은 디렉터리를 생성합니다). 이 디렉터리는 휠 사양에 정의된 유효한 .dist-info 디렉터리여야 합니다. 단, RECORD 또는 서명을 포함하지 않아도 됩니다. 이 훅은 이 디렉터리 안에 다른 파일도 생성할 수 있으며, 빌드 프런트엔드는 그러한 파일을 보존하되 그 외에는 무시해야 합니다. 이는 메타데이터가 빌드 시점의 결정에 의존하는 경우 빌드 백엔드가 실제 휠 빌드 단계에서 재사용할 수 있도록 이러한 결정을 편리한 형식으로 기록해야 할 수 있기 때문입니다.

이 메서드는 생성한 .dist-info 디렉터리의 전체 경로가 아닌 기본 이름을 유니코드 문자열로 반환해야 합니다.

빌드 프런트엔드에 이 정보가 필요하지만 메서드가 정의되지 않은 경우, build_editable을 호출하고 결과 메타데이터를 직접 확인해야 합니다.

휠에 넣을 내용

빌드 백엔드는 설치했을 때 편집 가능 설치가 되도록 생성된 휠을 파일로 채워야 합니다. 빌드 백엔드는 편집 가능 설치의 목표를 달성하기 위해 서로 다른 기법을 사용할 수 있습니다. 이 절에서는 예를 제공하며 규범적인 내용은 아닙니다.

  • 빌드 백엔드는 소스 트리의 루트 디렉터리를 포함하는 .pth 파일을 .whl 파일의 루트에 배치할 수 있습니다. 이 접근 방식은 간단하지만 그다지 정밀하지 않습니다. 그러나 충분히 괜찮은 것으로 간주될 수 있으며(특히 src 레이아웃을 사용하는 경우), 현재 setup.py develop이 수행하는 방식과 유사합니다.
  • editables 라이브러리는 높은 품질의 편집 가능 설치를 제공하는 프록시 모듈을 빌드하는 방법을 보여 줍니다. 이 라이브러리는 포함하거나 숨길 모듈의 목록을 받습니다. 가져오면 이러한 프록시 모듈은 소스 트리의 코드로 자신을 대체합니다. 경로 기반 메서드는 경로 아래의 모든 스크립트를 가져올 수 있게 하며, 여기에는 프로젝트 자체의 setup.py 및 일반적인 설치에는 포함되지 않을 다른 스크립트가 포함되는 경우가 많습니다. 프록시 전략은 경로 기반 메서드보다 더 높은 수준의 충실도를 달성할 수 있습니다.
  • 심볼릭 링크는 편집 가능한 설치를 구현하는 데 유용한 또 다른 메커니즘입니다. 이 글을 작성하는 시점에는 wheel 사양이 심볼릭 링크를 지원하지 않으므로, 대상 환경에서 심볼릭 링크를 설정하는 데 직접 사용할 수 없습니다. 그러나 백엔드는 소스 트리의 일부 build 디렉터리에 심볼릭 링크 구조를 생성하고, “editable” 휠의 .pth 파일을 통해 해당 디렉터리를 Python 경로에 추가할 수 있습니다. 이러한 방식으로 링크된 일부 파일이 Python 구현 또는 버전, ABI나 플랫폼에 의존하는 경우, 호환성 태그에 따라 서로 다른 디렉터리에 링크 구조를 생성하도록 주의해야 하며, 그래야 동일한 프로젝트 트리를 여러 환경에서 편집 가능한 모드로 설치할 수 있습니다.

프런트엔드 요구 사항

프런트엔드는 일반 휠과 동일한 방식으로 “editable” 휠을 설치해야 합니다. 이는 또한 편집 가능한 설치를 제거할 때 특별한 처리가 필요하지 않다는 의미입니다.

프런트엔드는 PEP 610을 준수하여 설치된 배포판의 .dist-info 디렉터리에 direct_url.json 파일을 생성해야 합니다. url 값은 프로젝트 디렉터리(즉, pyproject.toml을 포함하는 디렉터리)를 가리키는 file:// URL이어야 하며, dir_info 값은 {'editable': true}여야 합니다.

프런트엔드는 get_requires_for_build_editable 후크를 pyproject.toml 파일에 지정된 부트스트랩 요구 사항이 포함된 환경에서 실행해야 합니다.

프런트엔드는 prepare_metadata_for_build_editablebuild_editable 후크를 pyproject.toml의 부트스트랩 요구 사항과 get_requires_for_build_editable 후크가 지정한 요구 사항이 포함된 환경에서 실행해야 합니다.

프런트엔드는 build_editable에서 얻은 휠을 최종 사용자에게 노출해서는 안 됩니다. 설치 후 휠을 폐기해야 하며 캐시하거나 배포해서는 안 됩니다.

제한 사항

휠의 .data 디렉터리와 관련하여, 이 PEP는 site-packages에 설치되는 purelibplatlib 범주를 “editable”로 만드는 데 중점을 둡니다. 다른 범주인 headers, datascripts 등에 대해서는 특별한 조치를 제공하지 않습니다. 패키지 작성자는 console_scripts를 사용하고, scripts를 라이브러리 기능을 호출하는 작은 래퍼로 만들거나, 개발 중에는 소스 체크아웃에서 이를 관리하는 것이 좋습니다.

프로토타입

이 PEP를 작성하는 시점에는 다양한 프런트엔드와 백엔드에서 여러 프로토타입 구현을 사용할 수 있습니다. 가능한 접근 방식을 보여 주기 위해 아래에 링크를 제공합니다.

프런트엔드:

빌드 백엔드:

거부된 아이디어

editable 로컬 버전 식별자

editable 문자열을 포함하도록 빌드 백엔드가 로컬 버전 식별자를 덧붙이거나 수정하게 하자는 아이디어는, 로컬 버전 식별자를 포함하는 == 버전 지정자를 충족하지 못하므로 거부되었습니다. 달리 말해, pkg==1.0+local1.0+local.editable 버전으로 충족되지 않습니다.

가상 휠

또 다른 접근 방식은 PEP 662에서 제안되었으며, 여기서 빌드 백엔드는 소스 파일과 디렉터리에서 설치된 레이아웃으로의 매핑을 반환합니다. 그런 다음 설치 프런트엔드가 사용자에게 적절하다고 판단하는 어떤 방법으로든 편집 가능 설치를 실현합니다.

기능 측면에서 두 제안 모두 핵심적인 “편집 가능” 기능을 제공합니다.

주요 차이점은 PEP 662에서는 편집 가능 설치를 어떻게 실현할지 프런트엔드가 결정하도록 맡기는 반면, 이 PEP에서는 백엔드가 결정해야 한다는 점입니다. 원칙적으로 두 접근 방식 모두 주어진 프로젝트에 여러 편집 가능 설치 방법을 제공하고, 개발자가 설치 시점에 그중 하나를 선택하도록 할 수 있습니다.

이 PEP를 작성하는 시점에 커뮤니티가 편집 가능 설치에 대해 이론적으로나 실무적으로나 폭넓은 기대를 하고 있다는 점은 분명합니다. 실제로 이에 대해 폭넓은 경험이 있는 유일한 방법은 .pth를 통한 경로 삽입입니다(즉, setup.py develop이 수행하는 방식입니다).

프로젝트 작성자가 자신의 요구 사항에 가장 적합한 편집 메커니즘을 제공하는 백엔드를 선택하거나 해당 방법을 구현하고, 그것이 올바르게 작동하는지 테스트할 수 있도록 함으로써, 오늘날 이러한 “알 수 없는 미지 사항”을 가장 신뢰할 수 있는 방식으로 해결하는 데 PEP 660이 더 적합하다고 생각합니다. 프런트엔드에는 편집 가능 휠을 “어떻게” 설치할지에 대한 재량이 없으므로, 문제가 발생한 경우 조사할 곳은 빌드 백엔드 하나뿐입니다.

PEP PEP 662를 적용하면 프런트엔드, 백엔드 및 어쩌면 사양에서도 문제를 조사해야 합니다. 또한 명세를 서로 다른 방식으로 구현하는 서로 다른 프런트엔드가 프로젝트 작성자가 의도한 것과 다르게 동작하는 설치를 만들어 혼란을 초래할 가능성이 높으며, 더 나쁘게는 특정 프런트엔드나 IDE에서만 작동하는 프로젝트가 만들어질 가능성도 높습니다.

압축 해제된 휠

임시 디렉터리에 압축 해제된 휠을 만들고, 프런트엔드가 이를 대상 환경에 복사하도록 하는 prototype이 만들어졌습니다. 백엔드가 휠 아카이브를 쉽게 만들 수 있고 휠을 통신 메커니즘으로 사용하는 것이 PEP 517의 철학에 더 잘 부합하며, 따라서 프런트엔드의 작업을 더 단순하게 유지할 수 있기 때문에 이 접근 방식은 추진되지 않았습니다.

참고 자료