PEP 685 – 선택적 배포 의존성의 extra 이름 비교
- Author:
- Brett Cannon <brett at python.org>
- PEP-Delegate:
- Paul Moore <p.f.moore at gmail.com>
- Discussions-To:
- Discourse thread
- Status:
- Final
- Type:
- Standards Track
- Topic:
- Packaging
- Created:
- 08-Mar-2022
- Post-History:
- 08-Mar-2022
- Resolution:
- Discourse message
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 비교를 수행할 때 배포 extra 이름을 정규화하는 방법을 규정합니다. 이를 통해 도구가 extra 이름을 찾지 못하거나, 예상치 못한 이름과 실수로 일치시키는 일을 방지합니다.
동기
Provides-Extra 코어 메타데이터 명세는 엑스트라의 이름이 “유효한 Python 식별자여야 합니다”라고 명시합니다. PEP 508은 extra 마커의 값이 첫 문자 뒤에 문자, 숫자, 또는 ., -, _ 중 하나를 포함할 수 있다고 규정합니다. extra 이름을 어떻게 작성해야 하는지, 또는 비교를 위해 어떻게 정규화해야 하는지 설명하는 다른 PyPA 명세는 없습니다. 현존하는 패키징 관련 코드의 양이 많기 때문에, 커뮤니티의 현재 관행을 평가하고, 기존 코드 대부분을 망가뜨리지 않으면서도 도구 작성자들이 따르기로 합의할 수 있는 하나의 방식으로 표준화하는 것이 중요합니다.
일관된 표준이 없다는 문제는 pip 22가 extra adhoc-ssl을 이름 adhoc_ssl과 같은 것으로 간주하지 않는다는 점을 지적한 초기 논의에서 제기되었습니다.
근거
PEP 503은 배포 이름을 정규화하는 방법을 다음과 같이 규정합니다:
re.sub(r"[-_.]+", "-", name).lower()
이 방식은 -, _, . 문자가 연속된 부분을 모두 하나의 -로 축약합니다. 예를 들어, ---, ., __는 모두 - 하나로 변환됩니다. 이는 엑스트라 이름에 대한 코어 메타데이터 2.2 명세에 따른 유효한 Python 식별자를 생성하지 않습니다.
Setuptools 60은 다음 코드로 정규화를 수행합니다:
re.sub(r'[^A-Za-z0-9-.]+', '_', name).lower()
밑줄/_을 사용하는 점은 PEP 503이 하이픈/-을 사용하는 것과 다르며, 이 방식은 PEP 508에서 허용하는 범위 밖의 문자도 정규화합니다. PEP 503과 달리, .과 -의 연속은 하나의 _로 정규화되지 않습니다. 예를 들어 ..는 그대로 유지됩니다. 참고로, 이는 이 함수의 독스트링과 일치하지 않는데, 해당 독스트링은 영숫자가 아닌 모든 문자(-와 .를 포함)가 정규화되고 축약된다고 분명히 명시하고 있습니다.
pip 22의 경우 “extra 정규화 동작이 상당히 복잡하고 불규칙하기” [pip-erratic] 때문에 그 방식은 고려하지 않습니다.
명세
extra 이름을 비교할 때, 도구는 이름에 대해 PEP 503에 설명된 의미론을 사용하여 비교 대상 이름을 반드시 정규화해야 합니다(MUST):
re.sub(r"[-_.]+", "-", name).lower()
core metadata 명세는 Provides-Extra에 허용되는 이름이 PEP 508이 이름에 대해 규정한 것과 일치하도록 갱신될 것입니다. 이를 통해 extra 이름 규칙이 Name 필드의 이름 규칙과 일치하게 됩니다. 이는 무엇을 유효한 것으로 간주하는지를 바꾸므로, 코어 메타데이터 버전이 2.3으로 올라가게 됩니다.
core metadata를 작성하는 도구는 extra 이름을 반드시 정규화된 형태로 기록해야 합니다(MUST). 이는 Provides-Extra 필드와, Requires-Dist 필드에서 사용될 때의 extra 마커에 적용됩니다.
메타데이터를 생성하는 도구는 사용자가 정규화했을 때 같은 이름이 되는 extra 이름을 두 개 이상 지정한 경우 반드시 오류를 발생시켜야 합니다(MUST). 메타데이터를 생성하는 도구는 지정된 코어 메타데이터 버전 기준으로 유효하지 않은 엑스트라 이름이 주어지면 반드시 오류를 발생시켜야 합니다(MUST). 프로젝트의 메타데이터가 이전 코어 메타데이터 버전을 지정하고 있고 그 이름이 더 새로운 코어 메타데이터 버전에서는 유효하지 않은 경우, 해당 메타데이터를 읽는 도구는 사용자에게 경고해야 합니다(SHOULD). 도구는 유효하지 않은 extra 이름을 읽었을 때 사용자에게 경고해야 하며(SHOULD), 모호함을 피하기 위해 해당 이름을 무시해야 합니다(SHOULD). 도구는 원한다면 유효하지 않은 이름을 읽었을 때 경고 대신 오류를 발생시킬 수 있습니다(MAY).
하위 호환성
PEP 503 정규화와 PEP 508 이름 허용 규칙으로 옮겨 가면 기존의 유효한 이름은 모두 계속 유효합니다.
PyPI에 있는 휠 모음을 조사한 연구 [pypi-results]에 따르면, 유효 여부와 관계없이 PyPI의 모든 extra 이름을 고려할 때(단일 패키지 내의 이름만이 아니라) extra 이름 충돌 위험은 73건으로 제한되며, 유효한 이름만 살펴보면 충돌은 단 3건에 불과합니다:
dev-test:dev_test,dev-test,dev.testdev-lint:dev-lint,dev.lint,dev_lintapache-beam:apache-beam,apache.beam
코어 메타데이터를 작성하는 도구가 정규화된 이름만 기록하도록 요구하면, 기존의 유효하지 않은 extra 이름 문제는 시간이 지남에 따라 줄어들 것입니다.
보안 영향
충돌하는 extra 이름을 가진 배포 패키지의 경우, 도구가 결국 어떤 식으로든 시스템의 보안을 약화시키는 의존성을 설치하게 될 가능성이 있습니다. 이는 가설에 불과하며, 만약 그런 일이 발생한다면 그 의존성들을 함께 끌어온 배포 패키지보다는 그러한 extra 이름을 지정한 배포 패키지 쪽의 보안 문제일 가능성이 더 높습니다.
교육 방법
이는 일상적인 사용에서 사용자에게 드러나지 않아야 합니다. 사용자가 충돌하는 extra 이름을 선택할 때 이를 알리거나 막는 것은 도구의 몫입니다.
참조 구현
위의 코드 외에는 참조 구현이 제공되지 않지만, packaging project가 packaging.utils 모듈에 extra 이름 정규화를 구현하는 함수를 제공할 것으로 예상됩니다. 또한 extra 이름 비교도 적절하게 구현할 것입니다. 마지막으로, 이 프로젝트가 언젠가 메타데이터를 작성하는 기능을 갖추게 된다면 이 PEP도 구현할 것입니다.
전환 계획
빌드 도구가 버전 2.3, 즉 이 PEP를 따르는 코어 메타데이터를 생성했는데, 이 PEP를 알지 못하는 도구가 그 메타데이터를 소비할 위험이 있습니다(해당 도구가 직접 지원하지 않는 코어 메타데이터 버전을 읽으려고 시도하는 경우). 그런 경우, 사용자가 이전에는 동작했지만 이제는 실패하는 정규화되지 않은 이름으로 extra를 지정할 가능성이 있습니다.
따라서 이 PEP의 소비자 측을 생산자 측보다 우선적으로 지원하여, 사용자가 정규화되지 않은(그래서 향후 동작하지 않을 수 있는) extra 이름을 지정하고 있음을 알릴 수 있도록 해야 합니다.
기각된 아이디어
setuptools 60의 정규화 사용
처음에 이 PEP는 하위 호환성 문제를 최소화하기 위해 정규화에 setuptools safe_extra()를 사용하는 방안을 제안했습니다. 그러나 PyPI의 여러 휠을 확인한 결과, 모든 이름 규칙을 PEP 508 및 PEP 503 의미 체계로 표준화하는 것이 하위 호환성 문제를 최소한으로 일으키면서도 더 쉽고 장기적으로 더 나은 방법임이 분명해졌습니다.
미해결 문제
해당 없음
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.