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 메커니즘을 제공합니다. pip는 pip 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 파일의 기본 이름(전체 경로가 아님)을 유니코드 문자열로 반환해야 합니다.

확장 모듈이나 그 밖의 빌드 산출물을 바로 사용할 수 있도록, 부수 효과로 배포판의 제자리(in-place) 빌드를 수행할 수도 있습니다.

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

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

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

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

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

get_requires_for_build_editable

def get_requires_for_build_editable(config_settings=None):
    ...

이 훅은 build_editable 훅을 호출할 때 설치할, pyproject.toml 파일에 지정된 것 외의 추가 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 디렉터리의 전체 경로가 아닌 기본 이름(basename)을 유니코드 문자열로 반환해야 합니다.

빌드 프런트엔드가 이 정보를 필요로 하는데 이 메서드가 정의되어 있지 않다면, build_editable을 호출하고 그 결과로 생성된 메타데이터를 직접 확인해야 합니다.

휠에 넣을 내용

빌드 백엔드는 생성된 휠을, 설치했을 때 편집 가능 설치가 이루어지는 파일들로 채워야 합니다. 빌드 백엔드는 편집 가능 설치의 목표를 달성하기 위해 다양한 기법을 사용할 수 있습니다. 이 절은 예시를 제공하며 규범적이지 않습니다.

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

프런트엔드 요구 사항

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

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

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

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

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

제약 사항

휠의 .data 디렉터리와 관련하여, 이 PEP는 (site-packages에 설치되는) purelib 및 platlib 범주를 “편집 가능”하게 만드는 데 중점을 둡니다. headers, data, scripts 같은 다른 범주에 대해서는 특별한 대책을 마련하지 않습니다. 패키지 작성자는 console_scripts를 사용하거나, scripts를 라이브러리 기능을 감싸는 작은 래퍼로 만들거나, 개발 중에는 이들을 소스 체크아웃에서 관리하는 것을 권장합니다.

프로토타입

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

프런트엔드:

빌드 백엔드:

기각된 아이디어

editable 로컬 버전 식별자

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

가상 휠

또 다른 접근 방식은 PEP 662에서 제안되었습니다. 이 방식에서는 빌드 백엔드가 소스 파일과 디렉터리를 설치된 레이아웃에 대응시키는 매핑을 반환합니다. 그러면 사용자에게 적절하다고 판단하는 어떤 수단으로든 편집 가능 설치를 실현하는 것은 설치 프로그램 프론트엔드의 몫입니다.

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

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

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

저희는 PEP 660이 현재의 이러한 “알려지지 않은 미지”에 가장 확실한 방법으로 더 잘 대응한다고 생각합니다. 프로젝트 작성자가 자신의 요구 사항에 가장 잘 맞는 편집 가능 메커니즘을 제공하는 백엔드를 선택하거나 그런 방법을 직접 구현하고, 그것이 올바르게 동작하는지 테스트할 수 있기 때문입니다. 프런트엔드에는 “편집 가능” 휠을 어떻게 설치할지에 대한 재량이 없으므로, 문제가 생기면 조사할 곳은 빌드 백엔드 한 곳뿐입니다.

PEP 662에서는 프런트엔드와 백엔드, 그리고 경우에 따라서는 명세까지 조사해야 합니다. 또한 서로 다른 프런트엔드가 명세를 각기 다르게 구현하여 프로젝트 작성자가 의도한 것과 다르게 동작하는 설치를 만들어 낼 가능성도 높습니다. 이는 혼란을 일으키고, 더 나쁜 경우에는 특정 프런트엔드나 IDE에서만 동작하는 프로젝트를 낳습니다.

압축 해제된 휠

임시 디렉터리에 압축 해제된 휠을 만들고 프런트엔드가 이를 대상 환경으로 복사하는 프로토타입이 만들어졌습니다. 이 접근 방식은 채택되지 않았습니다. 백엔드 입장에서는 휠 아카이브를 만들기 쉽고, 휠을 전달 수단으로 쓰는 것이 PEP 517의 철학에 더 잘 맞으며, 그 결과 프런트엔드의 작업도 더 단순해지기 때문입니다.

참고 문헌