PEP 610 – 설치된 배포 패키지의 직접 URL 출처 기록
- Author:
- Stéphane Bidoul <stephane.bidoul at gmail.com>, Chris Jerdonek <chris.jerdonek at gmail.com>
- Sponsor:
- Alyssa Coghlan <ncoghlan at gmail.com>
- BDFL-Delegate:
- Pradyun Gedam <pradyunsg at gmail.com>
- Discussions-To:
- Discourse thread
- Status:
- Final
- Type:
- Standards Track
- Topic:
- Packaging
- Created:
- 21-Apr-2019
- Post-History:
- Resolution:
- Discourse message
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
PEP 440에 따르면 배포 패키지는 이름과 함께 버전 또는 직접 URL 참조로 식별할 수 있습니다(PEP440 Direct References 참조). 설치 후 이름과 버전은 프로젝트 메타데이터에 기록되지만, 배포 패키지가 직접 URL 참조로 식별된 경우 사용된 URL의 세부 정보를 얻을 방법이 현재는 없습니다.
이 제안은 설치 프런트엔드가 설치된 배포 패키지에 추가하는 추가 메타데이터를 정의합니다. 이 메타데이터는 설치된 패키지 데이터베이스를 조사하는 소비자가 사용할 수 있도록 직접 URL 출처를 기록합니다(PEP 376 참조).
동기
이 PEP의 원래 동기는 Python 환경을 다시 만들 수 있게 해 주는 “freeze” 작업을 제공하는 도구가 더 다양한 상황에서 동작할 수 있도록 하는 것이었습니다.
구체적으로 이 PEP는 pip issue #609를 해결하려는 데서 시작되었습니다. 즉, 직접 URL 참조로 설치된 배포 패키지가 있을 때 pip freeze의 동작을 개선하려는 것입니다. 이 PEP는 이를 구현하기 위한 최선의 방안에 관한 thread on discuss.python.org에 이어 작성되었습니다.
직접 URL 참조로부터의 설치
pip와 같은 Python 설치 프로그램은 패키지 색인에서 배포를 다운로드하여 설치할 수 있습니다. 또한 PEP440 Direct References에서 표준화된 바와 같이, 소스 아카이브와 버전 관리 시스템(VCS) 저장소의 임의 URL을 지정하는 요구 사항으로부터 소스 코드를 내려받아 설치할 수도 있습니다.
다시 말해 관련된 설치 모드는 두 가지입니다.
- 설치할 패키지가 이름과 버전 지정자로 지정되는 경우:
이 경우 설치 프로그램은 설치할 배포를 찾기 위해 패키지 색인을 살펴봅니다(pip의 경우 선택적으로--find-links를 사용할 수도 있습니다).
- 설치할 패키지가 직접 URL 참조로 지정되는 경우:
이 경우 설치 프로그램은 URL이 지정하는 대상(일반적으로 wheel, 소스 아카이브 또는 VCS 저장소)을 다운로드하여 설치합니다.이 모드에서 설치 프로그램은 일반적으로 임시 디렉터리에 소스 코드를 다운로드합니다. 그런 다음 필요하면 PEP 517 빌드 백엔드를 호출하여 wheel을 만들고, 그 wheel을 설치한 뒤 임시 디렉터리를 삭제합니다.
설치 후에는 사용자가 패키지를 내려받기 위해 요청한 URL의 흔적이 사용자 시스템에 전혀 남지 않습니다.
환경 고정하기
pip에는 설치된 Python 배포 패키지 데이터베이스를 조사하여 요구 사항 목록을 생성하는 pip freeze라는 명령도 있습니다. 이 명령의 주된 목표는 나중에 같은 환경을 최대한 충실하게 다시 설치할 수 있게 해 주는 요구 사항 목록을 사용자가 생성하도록 돕는 것입니다.
pip 버전 19.3 기준으로 pip freeze 명령은 설치된 각 배포 패키지(편집 가능 설치는 제외)에 대해 name==version 줄을 출력합니다. 같은 환경을 다시 설치한다는 목표를 달성하려면 (이름, 버전) 튜플이 배포 패키지의 변경 불가능한 버전을 가리켜야 합니다. 변경 불가능성은 Warehouse 같은 패키지 색인이 보장합니다. 사용할 패키지 색인은 보통 설치 프로그램의 환경 매개변수나 명령줄 매개변수를 통해 알 수 있습니다.
따라서 이 freeze 메커니즘은 설치 모드 1(즉, 설치할 패키지가 이름과 버전 지정자로 지정된 경우)에서는 잘 동작합니다.
설치 모드 2, 즉 설치할 패키지가 직접 URL 참조로 지정된 경우에는 name==version 튜플만으로는 같은 배포 패키지를 다시 설치하기에 분명히 부족하며, freeze 명령의 사용자는 원래 요청된 URL이 출력되기를 기대합니다.
위의 논리는 pip freeze 외에도 설치된 Python 배포 패키지 데이터베이스로부터 Pipfile.lock 또는 이와 유사한 형식을 생성하려는 도구에도 똑같이 적용됩니다. 달리 명시하지 않는 한, 이 문서에서 “freeze”는 이러한 작업을 가리키는 일반적인 용어로 사용됩니다.
애플리케이션 통합자에게 (VCS) URL로부터의 설치가 갖는 중요성
애플리케이션 통합자는 릴리스되지 않은 Python 배포 버전을 안정적으로 설치하고 고정(freeze)할 수 있어야 합니다. 예를 들어 개발자가 의존성의 패치 버전을 릴리스 전에 배포해야 할 때가 있습니다. 이럴 때는 유지 관리자가 업데이트된 버전을 릴리스할 때까지 기다리는 동안 패치가 적용된 VCS 브랜치에서 의존성을 직접 설치하는 경우가 많습니다.
이러한 경우 가능한 한 가장 높은 충실도로 재현 가능한 빌드를 만들려면 “freeze”가 설치된 정확한 VCS 참조(가능하다면 커밋 해시)를 고정하는 것이 중요합니다.
VCS URL에 대해 제공되는 추가 출처 메타데이터
VCS URL에는 설치 시점에만 얻을 수 있는 출처 정보가 추가로 있으며, 이 정보는 인트로스펙션과 특정 워크플로에 유용합니다. 예를 들어 VCS URL에서 리비전을 설치할 때, 도구는 해당 리비전이 브랜치, 태그 또는 (Git의 경우) ref 중 어디에 해당하는지 판별할 수 있습니다. 이 정보는 설치된 배포판 데이터베이스를 내부 검사할 때, 어떤 버전이 설치되었는지에 대한 더 많은 정보(예: 브랜치나 태그가 설치되었는지, 그렇다면 그 브랜치나 태그의 이름)를 사용자에게 알려 주는 데 사용할 수 있습니다. 또한 이를 통해 태그 형식으로 PEP 440 직접 참조 URL을 구성할 수 있는지도 알 수 있습니다. 불변성의 의미를 갖는 것은 태그뿐이기 때문입니다.
리비전이 변경 가능한 경우(예: 브랜치와 Git ref), 이 정보를 알면 사용자가 예컨대 추적 중인 브랜치의 최신 버전으로 업데이트하거나 로컬에서 리뷰 중인 풀 리퀘스트의 최신 버전으로 업데이트하는 워크플로가 가능해집니다. 반대로 리비전이 태그인 경우, 도구는 업데이트가 필요하지 않다는 것을 미리(예: 네트워크 호출 없이) 알 수 있습니다.
URL 자체와 마찬가지로, 이 정보도 VCS 저장소를 사용할 수 있는 설치 시점에 기록하지 않으면 유실됩니다.
“편집 가능(editable)” 설치에 관한 참고 사항
pip의 편집 가능 설치 모드는 대략적으로 말해 사용자가 개발 목적으로 로컬 디렉터리를 sys.path에 삽입할 수 있게 해 줍니다. 이 모드는 VCS URL에서 편집 불가능한 방식으로 설치하면 설치 후 출처를 추적할 수 없게 된다는 문제를 우회하기 위해 다소 남용되고 있습니다. 실제로 편집 가능 설치는 체크아웃 디렉터리에 VCS 출처를 암묵적으로 기록하므로, “freeze”를 실행할 때 그 정보를 복구할 수 있습니다.
이 우회 방법은 유용하기는 하지만 취약하고, 편집 가능 모드의 목적에 대한 혼란을 일으키며, 배포판을 setuptools로 설치할 수 있는 경우에만 동작합니다(즉, 다른 PEP 517 빌드 백엔드에서는 사용할 수 없습니다).
이 PEP가 구현되면 pip freeze가 VCS 참조와 함께 올바르게 동작하도록 하기 위해 더 이상 편집 가능 설치를 사용할 필요가 없습니다.
근거
이 PEP는 설치된 배포판의 .dist-info 디렉터리에 새로운 direct_url.json 메타데이터 파일을 명시합니다.
명시된 필드는 소스 아카이브와 VCS URLs supported by pip를 재현하기에 충분합니다. 또한 이 필드들은 PEP440 Direct References와 Pipfile and Pipfile.lock 항목을 재현하기에도 충분합니다. 마지막으로, 이 필드들은 설치된 버전의 브랜치, 태그 및/또는 Git ref 출처를 기록하기에도 충분합니다. 이 정보는 편집 가능 설치에서는 VCS 체크아웃이 존재하기 때문에 이미 얻을 수 있습니다.
이러한 유형의 정보를 인코딩하는 방법이 이미 적어도 세 가지 존재하므로, 이 PEP는 직접 URL 참조가 최종적으로 요구 사항이나 잠금 파일에 어떻게 인코딩되어야 하는지에 대해 어떠한 가정도 하지 않도록 딕셔너리 형식을 사용합니다. 이 선택에 대한 더 자세한 논의는 아래의 Alternatives 절도 참고하십시오.
유사한 기능을 갖추고 있는지 확인하고 이 명세의 필드 선정과 명명에 참고하기 위해 Ruby의 bundler 매뉴얼에서 정보를 가져왔습니다.
JSON 형식은 향후 필드를 더 추가할 수 있도록 해 줍니다.
명세
이 PEP는 배포판의 직접 URL 출처(Direct URL Origin)를 기록하기 위해, 설치된 배포판의 .dist-info 디렉터리에 direct_url.json 파일을 명시합니다.
이 메타데이터 파일의 이름과 의미에 대한 공식 출처는 Recording the Direct URL Origin of installed distributions 문서입니다.
직접 URL 참조(VCS URL 포함)를 지정하는 요구 사항으로 배포를 설치할 때, 설치 프로그램은 반드시(MUST) 이 파일을 생성해야 합니다.
다른 유형의 요구 사항(즉, 이름과 버전 지정자)으로부터 배포판을 설치할 때는 이 파일을 생성해서는 안 됩니다(MUST NOT).
이 JSON 파일은 반드시(MUST) RFC 8259를 준수하고 UTF-8로 인코딩된 딕셔너리여야 합니다.
이 항목이 있는 경우, 최소 두 개의 필드를 반드시 포함해야 합니다. 첫 번째 필드는 string 타입의 url입니다. url이 무엇을 가리키는지에 따라 두 번째 필드는 vcs_info (url이 VCS 참조인 경우), archive_info (url이 소스 아카이브나 휠인 경우), dir_info (url이 로컬 디렉터리인 경우) 중 하나여야 합니다. 이 정보 필드들은 (비어 있을 수도 있는) 하위 딕셔너리를 값으로 가지며, 사용할 수 있는 키는 아래에 정의되어 있습니다.
보안상의 이유로 url에서는 민감한 인증 정보를 모두 제거해야 합니다.
다만 URL의 user:password 부분은 다음 정규 표현식과 일치하는 환경 변수로 구성할 수 있습니다.:
\$\{[A-Za-z0-9-_]+\}(:\$\{[A-Za-z0-9-_]+\})?
또한 URL의 user:password 부분은 널리 알려져 있고 보안상 민감하지 않은 문자열일 수 있습니다. 대표적인 예로 ssh://git@gitlab.com과 같은 URL의 git이 있습니다.
url이 VCS 저장소를 가리키는 경우, vcs_info 키가 다음 키를 가진 딕셔너리로 반드시 있어야 합니다.
- VCS의 이름(즉,
git,hg,bzr,svn중 하나)을 담은vcs키(타입string)가 반드시 있어야 합니다. 그 밖의 VCS는 이 명세를 개정하는 PEP를 작성하여 등록하는 것이 좋습니다.url값은 해당 VCS와 반드시(MUST) 호환되어야 합니다. 그래야 설치 프로그램이 이 값을 변환하지 않고 VCS의 checkout/download 명령에 그대로 넘길 수 있습니다. - 설치할 브랜치/태그/ref/커밋/리비전 등을 (VCS와 호환되는 형식으로) 지정하는
requested_revision키(타입string)가 있을 수 있습니다. - 설치된 정확한 커밋/리비전 번호를 담은
commit_id키(타입string)가 반드시 있어야 합니다. VCS가 커밋 해시 기반의 리비전 식별자를 지원한다면, 설치된 소스 코드의 불변 버전을 참조할 수 있도록 해당 커밋 해시를commit_id로 사용해야 합니다. - 설치 프로그램이 요청된 리비전에 대해 추가 정보를 알아낼 수 있다면,
resolved_revision필드나resolved_revision_type필드를 추가하거나 둘 다 추가할 수 있습니다(MAY). 요청된 URL에 리비전이 지정되지 않았다면resolved_revision에는 설치된 기본 브랜치가 들어갈 수 있으며, 이때resolved_revision_type은branch가 됩니다. 설치 프로그램이requested_revision이 태그였다고 판단하면, 값이tag인resolved_revision_type을 추가할 수 있습니다(MAY).
url이 소스 아카이브나 휠을 가리키는 경우, archive_info 키가 다음 키를 가진 딕셔너리로 반드시 있어야 합니다.
- 값이
<hash-algorithm>=<expected-hash>인hash키(타입string)가 있는 것이 좋습니다. 소스 아카이브 해시에는 표준 라이브러리hashlib모듈의 최신 버전이 조건 없이 제공하는 해시만 사용하기를 권장합니다. 이 글을 쓰는 시점에서 해당 목록은 ‘md5’, ‘sha1’, ‘sha224’, ‘sha256’, ‘sha384’, ‘sha512’로 구성됩니다.
url이 로컬 디렉터리를 가리키는 경우, dir_info 키가 다음 키를 가진 딕셔너리로 반드시 있어야 합니다.
editable(타입:boolean): 배포 패키지가 편집 가능 모드로 설치되었다면true, 그렇지 않으면false입니다. 이 키가 없으면 기본값은false입니다.
url이 로컬 디렉터리를 가리키는 경우, 반드시 file 스킴을 사용하고 RFC 8089를 준수해야 합니다. 특히 경로 부분은 절대 경로여야 합니다. 상대 경로를 절대 경로로 바꿀 때에는 심볼릭 링크를 유지하는 것이 좋습니다.
Note
요청된 URL이 file:// 스킴을 사용하고, 그 URL이 가리키는 로컬 디렉터리에 마침 VCS 체크아웃이 들어 있는 경우가 있습니다. 이때 설치 프로그램은 VCS 정보를 추론하려고 시도해서는 안 되며(MUST NOT), 따라서 direct_url.json에 VCS 관련 정보(vcs_info 등)를 출력해서도 안 됩니다(MUST NOT).
pyproject.toml 또는 setup.py의 위치를 지정하기 위해, VCS 저장소, 소스 아카이브 또는 로컬 디렉터리의 루트를 기준으로 한 디렉터리 경로를 담은 최상위 subdirectory 필드가 있을 수 있습니다.
Note
일반적으로 설치 프로그램은 direct_url.json을 생성할 때 요청된 URL에 들어 있던 정보를 최대한 보존해야 합니다. 예를 들어 user:password 환경 변수는 보존되어야 하며, requested_revision은 요청된 URL에 제공된 리비전을 가능한 한 충실하게 반영해야 합니다. 다만 이 정보는 commit_id와 같은 더 정확한 데이터로 보강됩니다.
등록된 VCS
이 절에서는 등록된 VCS 목록, vcs_info의 vcs, requested_revision 및 기타 필드를 사용하는 방법에 대한 VCS별 상세 정보, 그리고 경우에 따라 추가적인 VCS별 필드를 제시합니다. 도구는 다른 VCS를 지원할 수 있지만, 이 명세를 개정하는 PEP를 작성하여 해당 VCS를 등록할 것을 권장합니다. vcs 필드는 (소문자로 된) 명령 이름이어야 합니다. 그러한 VCS를 지원하는 데 필요한 추가 필드에는 VCS 명령 이름을 접두사로 붙여야 합니다.
Git
홈페이지
vcs 명령
git
vcs 필드
git
requested_revision 필드
태그 이름, 브랜치 이름, Git ref, 커밋 해시, 축약된 커밋 해시 또는 기타 commit-ish입니다.
commit_id 필드
커밋 해시(16진수 40자로 된 sha1)입니다.
Note
설치 프로그램은 git show-ref 및 git symbolic-ref 명령을 사용하여 requested_revision이 Git ref에 해당하는지 판단할 수 있습니다. 그리고 refs/tags/로 시작하는 ref는 태그에 해당하고, 클론한 후 refs/remotes/origin/으로 시작하는 ref는 브랜치에 해당합니다.
Mercurial
홈페이지
vcs 명령
hg
vcs 필드
hg
requested_revision 필드
태그 이름, 브랜치 이름, 체인지셋 ID 또는 축약된 체인지셋 ID입니다.
commit_id 필드
체인지셋 ID(16진수 40자)입니다.
Bazaar
홈페이지
vcs 명령
bzr
vcs 필드
bzr
requested_revision 필드
태그 이름, 브랜치 이름, 리비전 ID입니다.
commit_id 필드
리비전 ID입니다.
Subversion
홈페이지
vcs 명령
svn
vcs 필드
svn
requested_revision 필드
requested_revision은svn checkout의--revision옵션과 호환되어야 합니다. Subversion에서는 브랜치나 태그가url의 일부입니다.
commit_id 필드
Subversion은 전역적으로 고유한 식별자를 지원하지 않으므로, 이 필드는 해당 저장소의 Subversion 리비전 번호입니다.
예시
direct_url.json 예시
소스 아카이브:
{
"url": "https://github.com/pypa/pip/archive/1.3.1.zip",
"archive_info": {
"hash": "sha256=2dc6b5a470a1bde68946f263f1af1515a2574a150a30d6ce02c6ff742fcc0db8"
}
}
태그와 커밋 해시가 있는 Git URL:
{
"url": "https://github.com/pypa/pip.git",
"vcs_info": {
"vcs": "git",
"requested_revision": "1.3.1",
"resolved_revision_type": "tag",
"commit_id": "7921be1537eac1e97bc40179a57f0349c2aee67d"
}
}
로컬 디렉터리:
{
"url": "file:///home/user/project",
"dir_info": {}
}
편집 가능 모드로 설치된 로컬 디렉터리:
{
"url": "file:///home/user/project",
"dir_info": {
"editable": true
}
}
pip 명령 예시와 각 명령이 direct_url.json에 미치는 영향
direct_url.json을 생성하는 명령:
- pip install https://example.com/app-1.0.tgz
- pip install https://example.com/app-1.0.whl
- pip install “git+https://example.com/repo/app.git#egg=app&subdirectory=setup”
- pip install ./app
- pip install file:///home/user/app
- pip install –editable “git+https://example.com/repo/app.git#egg=app&subdirectory=setup” (이 경우
url은 git 저장소가 복제된 로컬 디렉터리가 되며,dir_info는"editable": true와 함께 존재하고vcs_info는 설정되지 않습니다) - pip install -e ./app
direct_url.json을 생성하지 않는 명령
- pip install app
- pip install app –no-index –find-links https://example.com/
사용 사례
환경 “고정(freezing)”
pip freeze와 같이 설치된 Python 배포판 데이터베이스(Database of Installed Python Distributions)로부터 요구 사항을 생성하는 도구는, 더 높은 충실도의 출력을 생성하기 위해direct_url.json이 존재하면 이를 활용해야 하며(SHOULD), Version 메타데이터보다 이를 우선해야 합니다.vcs직접 URL 참조가 있는 경우, 원래 설치된 버전에 대해 가능한 한 가장 높은 충실도를 제공하기 위해commit_id필드를 우선적으로 사용해야 합니다(SHOULD). 도구의 요구 사항 형식이 지원한다면,tag값은 불변의 의미를 가지므로 해당 값이 있을 경우 이를 함께 출력할 것을 권장합니다. 도구는 사용자의 필요에 따라 다른 접근 방식을 선택할 수 있습니다(MAY).이 PEP의 초기 버전은 편집 가능한 설치나 로컬 디렉터리로부터의 설치를 포함하는 환경을 재현 가능하게 만들려고 하지는 않지만, 그러한 환경을 쉽게 식별할 수 있도록 하려고 한다는 점에 유의하십시오. 이 명세의
url및dir_info필드를 통해 로컬 프로젝트 디렉터리의 위치를 찾음으로써, 도구는 자신의 사용 사례에 맞는 어떤 전략이든 구현할 수 있습니다.
하위 호환성
이 PEP는 .dist-info 디렉터리에 새 파일을 명시하므로, 하위 호환성에 미치는 영향은 없습니다.
대안
PEP 426 source_url
현재는 철회된 PEP 426은 source_url 메타데이터 항목을 명시합니다. 이는 distlib에도 구현되어 있습니다.
이는 sdist에서 사용하기 위한, 약간 다른 목적으로 의도되었습니다.
이 형식은 pip 요구 사항 URL의 subdirectory 옵션을 지원하지 않습니다. 동일한 제약이 PEP440 직접 참조에도 존재합니다.
또한 environment variables in the user:password part of URLs에 대한 명시적인 지원도 없습니다.
이 PEP에서 사용하려면 키/값 확장 메커니즘의 도입과 PEP 440에서 user:password에 대한 환경 변수 지원이 필요합니다.
revision 대 ref
requested_revision은 다양한 VCS 전반에 걸쳐 더 일반적인 용어이고 ref는 git에서 특정한 의미를 가지므로, requested_ref 대신 requested_revision 키를 유지했습니다.
참고 문헌
감사의 글
여러분의 도움으로 이 PEP가 실현될 수 있었습니다. Paul F. Moore는 초록의 핵심 내용을 제공했습니다. Alyssa Coghlan은 direct_url이라는 이름을 제안했습니다.
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.