рд╡рд╛рддрд╛рд╡рд░рдг
рд╡рд┐рд╡рд░рдг
рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдПрдХ six
рдмрдЧ рдпрд╛ рдкрд┐рдк рдмрдЧ рд╣реИред рдХреНрд╖рдорд╛ рдХрд░реЗрдВ рдпрджрд┐ рдпрд╣ six
ред
рдкрд┐рдк рдореЗрдВ рд╕реНрдерд╛рдиреАрдп рдкрде рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реБрдЖ рдкреНрд░рддреАрдд install_requires
рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ name @ ./some/path
, рд▓реЗрдХрд┐рди рдпреВрдЖрд░рдПрд▓ рдкрд╛рд░реНрд╕ рдмрд╣реБрдд рдЯреВрдЯ рдЧрдпрд╛ рд╣реИред
рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ, рдпрд╣ рдЖрдиреЗ рд╡рд╛рд▓реЗ URL рдХреЗ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдШрдЯрдХреЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП urlsplit
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред
рдпрд╣рд╛рдБ рд╡рд╣ рд╣реИ рдЬреЛ рдЗрдирдкреБрдЯ рдХреЗ рдХреБрдЫ рдЯреБрдХрдбрд╝реЛрдВ рдХреЗ рд╕рд╛рде рджрд┐рдЦрддрд╛ рд╣реИ:
./foo/bar -> SplitResult(scheme='', netloc='', path='./foo/bar', query='', fragment='')
file:./foo/bar -> SplitResult(scheme='file', netloc='', path='./foo/bar', query='', fragment='')
file://./foo/bar -> SplitResult(scheme='file', netloc='.', path='/foo/bar', query='', fragment='')
netloc
.
рдЦрд╛рд▓реА рд╣реЛрдиреЗ рдХреЗ рдмрдЬрд╛рдп рдФрд░ path
рдирд┐рд░рдкреЗрдХреНрд╖ рд╣реЛрдиреЗ рдХреЗ рдмрдЬрд╛рдп, рд╕реНрдерд╛рдиреАрдп рдирд╣реАрдВ рд╣реЛрдиреЗ рдкрд░ рдЕрдВрддрд┐рдо рдкрд░рд┐рдгрд╛рдо рджреЗрдЦреЗрдВред рдпрд╣ рдЧреИрд░-рд╕реНрдерд╛рдиреАрдп рд░рд╛рд╕реНрддреЛрдВ рдХреЗ рд╕рдВрдмрдВрдз рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рддрд╛ рд╣реИред рдпрд╣ рд╕рдм рдареАрдХ рд╣реИ рдФрд░ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рд╣реИ - рдореИрдВ рд╕рд╢рд░реНрдд рддрд░реНрдХ рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рджреВрд╕рд░реЗ рд░реВрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ (рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкрд╣рд▓реЗ рдХрд╛ рднреА рд╕рдорд░реНрдерди рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП)ред
рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡рд╣рд╛рдБ рддрд░реНрдХ рддрд░реНрдХ рдХрд╣реАрдВ рдФрд░ рд╣реИ ...
рдпрд╣ рд╡рд╣ рддрд░реНрдХ рд╣реИ рдЬреЛ рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдЬрдмрдХрд┐ рд╣рдо рдкреВрд░реНрд╡ рддрд░реНрдХ рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдХрд░рддреЗ рд╣реИрдВред
рдпрд╣рд╛рдБ рдПрдХ рдкрд░реАрдХреНрд╖рдг рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ рд╕рдорд╕реНрдпрд╛ рджрд┐рдЦрд╛рддрд╛ рд╣реИ:
from six.moves.urllib import parse as urllib_parse
def tryparse(url):
print(url)
parsed = urllib_parse.urlparse(url)
unparsed = urllib_parse.urlunparse(parsed)
parsed_again = urllib_parse.urlparse(unparsed)
print(parsed)
print(unparsed)
print(parsed_again)
рдпрд╣рд╛рдБ ./foo/bar
рдХреЗ рд▓рд┐рдП рдЖрдЙрдЯрдкреБрдЯ рд╣реИ:
>>> tryparse('./foo/bar')
./foo/bar
ParseResult(scheme='', netloc='', path='./foo/bar', params='', query='', fragment='')
./foo/bar
ParseResult(scheme='', netloc='', path='./foo/bar', params='', query='', fragment='')
рд╕рднреА рдЕрдЪреНрдЫреЗ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ file:
рдХреА рдпреЛрдЬрдирд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдкрд╣рд▓реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рддрд░реНрдХ рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред
рдпрд╣рд╛рдБ file:./foo/bar
рдХреЗ рд▓рд┐рдП рдЖрдЙрдЯрдкреБрдЯ рд╣реИ:
>>> tryparse('file:./foo/bar')
file:./foo/bar
ParseResult(scheme='file', netloc='', path='./foo/bar', params='', query='', fragment='')
file:///./foo/bar
ParseResult(scheme='file', netloc='', path='/./foo/bar', params='', query='', fragment='')
рдКрдкреНрд╕! рд╕реВрдЪрдирд╛ рдХреИрд╕реЗ, рдЬрдм рд╣рдо "unparse" рдкрд╣рд▓реЗ рдкрд╛рд░реНрд╕ рдХреЙрд▓ рд╕реЗ рдкрд░рд┐рдгрд╛рдо, рд╣рдорд╛рд░реЗ path
рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдкреВрд░реНрдг file:///...
ред
рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рджреВрд╕рд░рд╛ рдЙрд▓реНрд▓рд┐рдЦрд┐рдд рдЪреЗрдХ рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ - рдкрде рд╕реНрдерд╛рдиреАрдп рдирд╣реАрдВ рд╣реИред рдореЗрд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдпрд╣ six
рдореЗрдВ рдПрдХ рдмрдЧ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди scheme in ['file', '']
рдЕрдиреБрдорддрд┐ рджреЗрдХрд░ рдФрд░ ./foo/bar
URI рдлреЙрд░реНрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рдирд┐рд░реНрджреЗрд╢ рджреЗрдХрд░ рдкрд┐рдк рдореЗрдВ рд╢рдорди рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рддрд░реНрдХ рдХреЗ рдЗрди рджреЛ рд╡рд┐рд░реЛрдзрд╛рднрд╛рд╕реА рдЯреБрдХрдбрд╝реЛрдВ рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП, install_requires
рдХреБрдВрдЬреА рдореЗрдВ distutils
рдпрд╛ setuptools
рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдореЗрдВ рд╕реНрдерд╛рдиреАрдп рдкрдереЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЕрд╕рдВрднрд╡ рд╣реИред
рдЕрдкреЗрдХреНрд╖рд┐рддреН рд╡реНрдпрд╡рд╣рд╛рд░
рдореБрдЭреЗ рдЕрдкрдиреЗ рдХреЛрдбрдмреЗрд╕ рдореЗрдВ рд╕реНрдерд╛рдиреАрдп рд╢реНрд░реЗрдгреА рдХреЗ рдкреИрдХреЗрдЬ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП name @ ./some/path
(рдпрд╛, рдИрдорд╛рдирджрд╛рд░реА рд╕реЗ, ./some/path
) рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
рдХреИрд╕реЗ рдкреБрди: рдкреЗрд╢ рдХрд░реЗрдВ
#!/usr/bin/env bash
mkdir /tmp/pip-uri-repro && cd /tmp/pip-uri-repro
mkdir -p foo/bar
cat > requirements.txt <<EOF
./foo
EOF
cat > foo/setup.py <<EOF
#!/usr/bin/env python
from setuptools import setup
setup(
name="foo",
version="0.1",
install_requires=[
"bar @ file:./bar"
]
)
EOF
cat > foo/bar/setup.py <<EOF
#!/usr/bin/env python
from setuptools import setup
setup(
name="bar",
version="0.1"
)
EOF
# (OUTPUT 1)
pip install -r requirements.txt
cat > foo/setup.py <<EOF
#!/usr/bin/env python
from setuptools import setup
setup(
name="foo",
version="0.1",
install_requires=[
# we're forced to use an absolute path
# to make the "Invalid URL" error go
# away, which isn't right anyway (the
# error that is raised as a result
# is justified)
"bar @ file://./bar"
]
)
EOF
# (OUTPUT 2)
pip install -r requirements.txt
рдЙрддреНрдкрд╛рджрди
рдкрд╣рд▓реЗ pip install
:
Processing ./foo
ERROR: Complete output from command python setup.py egg_info:
ERROR: error in foo setup command: 'install_requires' must be a string or list of strings containing valid project/version requirement specifiers; Invalid URL given
рджреВрд╕рд░реЗ pip install
:
Processing ./foo
ERROR: Exception:
Traceback (most recent call last):
File "/private/tmp/repro-pip-egg/env3/lib/python3.7/site-packages/pip/_internal/cli/base_command.py", line 178, in main
status = self.run(options, args)
File "/private/tmp/repro-pip-egg/env3/lib/python3.7/site-packages/pip/_internal/commands/install.py", line 352, in run
resolver.resolve(requirement_set)
File "/private/tmp/repro-pip-egg/env3/lib/python3.7/site-packages/pip/_internal/resolve.py", line 131, in resolve
self._resolve_one(requirement_set, req)
File "/private/tmp/repro-pip-egg/env3/lib/python3.7/site-packages/pip/_internal/resolve.py", line 294, in _resolve_one
abstract_dist = self._get_abstract_dist_for(req_to_install)
File "/private/tmp/repro-pip-egg/env3/lib/python3.7/site-packages/pip/_internal/resolve.py", line 242, in _get_abstract_dist_for
self.require_hashes
File "/private/tmp/repro-pip-egg/env3/lib/python3.7/site-packages/pip/_internal/operations/prepare.py", line 256, in prepare_linked_requirement
path = url_to_path(req.link.url)
File "/private/tmp/repro-pip-egg/env3/lib/python3.7/site-packages/pip/_internal/download.py", line 521, in url_to_path
% url
ValueError: non-local file URIs are not supported on this platform: 'file://./bar'
рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВ:
рдмрд╕ рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ RFC 3986 рдпрд╣ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рд╕рд╛рдкреЗрдХреНрд╖ рдкрде URI рдХреЛ file:
рдпреЛрдЬрдирд╛ рдХреЗ рд╕рд╛рде рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рддрдХрдиреАрдХреА рд░реВрдк рд╕реЗ six
file:./foo/bar
рдкрд░ рдЧрд▓рдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐, рддрдХрдиреАрдХреА рд░реВрдк рд╕реЗ, рдореБрдЭреЗ рдЕрдкрдиреЗ setup.py рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:
PKG_DIR = os.path.dirname(os.path.abspath(__file__))
install_requires = [
f"name @ file://{PKG_DIR}/foo/bar"
]
рд╣рд╛рд▓рд╛рдВрдХрд┐, рдкрд╛рдЗрдк /tmp
рдореЗрдВ рдкреИрдХреЗрдЬ рдХреА "рд╕рд╛рдл" рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдиреЗ рд▓рдЧрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ file:///tmp/pip-req-build-9u3z545j/foo/bar
рдЬреИрд╕рд╛ рдХреБрдЫ рдорд┐рд▓рддрд╛ рд╣реИред
рдЕрдкрдиреЗ рдкрд░реАрдХреНрд╖рдг рдХрд╛рд░реНрдп рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ, рд╣рдо рджреВрд╕рд░реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╢рд░реНрдд рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдХрд░рддреЗ рд╣реИрдВ:
>>> tryparse('file:///tmp/pip-req-build-9u3z545j/foo/bar')
file:///tmp/pip-req-build-9u3z545j/foo/bar
ParseResult(scheme='file', netloc='', path='/tmp/pip-req-build-9u3z545j/foo/bar', params='', query='', fragment='')
file:///tmp/pip-req-build-9u3z545j/foo/bar
ParseResult(scheme='file', netloc='', path='/tmp/pip-req-build-9u3z545j/foo/bar', params='', query='', fragment='')
рд╡рд╣рд╛рдВ рд╕рдм рдХреБрдЫ рдЕрдЪреНрдЫрд╛ рд╣реИред "рдЕрдирдкреЗрдХреНрд╖рд┐рдд" рдПрдХ рд╣реА рдкрд░рд┐рдгрд╛рдо рджреЗрддрд╛ рд╣реИ, рдФрд░ netloc
рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЛ рдкрд╣рд▓реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╢рд░реНрдд рдХреЗ рд▓рд┐рдП рдкреВрд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рд╣рд╛рд▓рд╛рдБрдХрд┐, рд╣рдо рдЕрднреА рднреА Invalid URL
рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде рдорд┐рд▓реЗ рд╣реИрдВ, рднрд▓реЗ рд╣реА рджреВрд╕рд░реЗ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рддрд░реНрдХ рд╕рдВрддреБрд╖реНрдЯ рд╣реЛред
рдЪреВрдВрдХрд┐ pip
(рдпрд╛ рдбрд┐рд╕реНрдЯрд▓реНрдпреВрдЯ рдпрд╛ рд╕реЗрдЯрдкреВрд▓ рдпрд╛ рдЬреЛ рднреА) рдЖрдЙрдЯрдкреБрдЯ рдирд┐рдЧрд▓рддрд╛ рд╣реИ, рдореИрдВ рдЖрдЧреЗ рдмрдврд╝рд╛ рдФрд░ рдЕрдкрдиреЗ setup.py рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрд┐рдпрд╛ред
import os
PKG_DIR = os.path.dirname(os.path.abspath(__file__))
assert False, os.system(f"find {PKG_DIR}")
рдЬреЛ рдпрд╣ рдкреБрд╖реНрдЯрд┐ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рд╕рднреА рдлрд╛рдЗрд▓реЗрдВ рд╡рд╣рд╛рдБ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╣реИ - рдЗрд╕рд▓рд┐рдП рдпрд╣ рдлрд╝рд╛рдЗрд▓ рдЧреБрдо рдпрд╛ рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреА рд╣реИред рдКрдкрд░ рдХреА рд▓рд╛рдЗрди рдЬрд┐рд╕рдореЗрдВ "Invalid URL given"
рд╣реИ рд╡рд╣ рдХреЛрдбрдмреЗрд╕ рдХрд╛ рдПрдХрдорд╛рддреНрд░ рд╕реНрдерд╛рди рд╣реИ рдЬреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рджрд┐рдЦрд╛рддрд╛ рд╣реИред
рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░, рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ рд╕рдорд╕реНрдпрд╛ рдХреНрдпрд╛ рд╣реИред
рдареАрдХ рд╣реИ, рдореИрдВ рд╕рдорд╕реНрдпрд╛ рджреЗрдЦрддрд╛ рд╣реВрдВред setuptools
, pkg-resources
рдФрд░ pip
рд╕рднреА packaging
рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рдереЛрдбрд╝реЗ рдЕрд▓рдЧ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
pip
, рдпрд╣ рд╡рд╣ рд╕рдВрд╕реНрдХрд░рдг рд╣реИ рдЬреЛ рдореИрдВрдиреЗ рдКрдкрд░ рджрд┐рдЦрд╛рдпрд╛ рдерд╛ред
рд╣рд╛рд▓рд╛рдБрдХрд┐, рдмрд╛рдХреА рд╕рдм рдореЗрдВ, рдпрд╣ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реИ (рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ "рдирдпрд╛" рдПрдХ рд╣реИ, рд▓реЗрдХрд┐рди рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рддрд░реНрдХ рдмрд╣реБрдд рд╕реАрдорд┐рдд рд╣реИ рдФрд░ RFC 3986 рдХреЗ рдЕрдиреБрд╕рд╛рд░ file:///
рдЕрдиреБрд╕рд╛рд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрдиреБрдкрд╛рд▓рди рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдПрдХ рдЦрд╛рд▓реА netloc
):
if req.url:
parsed_url = urlparse.urlparse(req.url)
if not (parsed_url.scheme and parsed_url.netloc) or (
not parsed_url.scheme and not parsed_url.netloc):
raise InvalidRequirement("Invalid URL given")
ЁЯЩД
рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЬрдм рд╕реЗ рдореЗрд░реА рдлрд╝рд╛рдЗрд▓рдкрде рдореЗрдВ file:///foo/bar
рдФрд░ file://localhost/foo/bar
рддрдм рддрдХ рдпрд╣ рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИред
рдпрд╣рд╛рдБ рдкреВрд░рд╛ рд╕рдорд╛рдзрд╛рди рд╣реИ :
import os
from setuptools import setup
PKG_DIR = os.path.dirname(os.path.abspath(__file__))
setup(
install_requires=[
f'foo @ file://localhost{PKG_DIR}/foo/bar'
]
)
рдпрд╣ рдЕрд╕реНрдкрд╖реНрдЯ рдФрд░ рд╕рдордп рдмрд░реНрдмрд╛рдж рдХрд░рдиреЗ рд╡рд╛рд▓реА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рдмреБрд░рд╛ UX рдорд┐рд╢реНрд░рд┐рдд рд╣реИред
рд╣рдо рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдХреЛ рдХреИрд╕реЗ рд╕реБрдзрд╛рд░ рд╕рдХрддреЗ рд╣реИрдВ?
@ Qix- рдЦреБрд╢реА рд╣реИ рдХрд┐ рдЖрдкрдиреЗ рдпрд╣ рдкрд╛рдпрд╛! рдореИрдВ рджреАрд╡рд╛рд░ рдХреЗ рдЦрд┐рд▓рд╛рдл рдЕрдкрдиреЗ рд╕рд┐рд░ рдХреЛ рдорд╛рд░ рд░рд╣рд╛ рдерд╛ рд╕рднреА рд╕рдорд╛рди рд╕реНрд╡рд░реВрдкреЛрдВ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рдерд╛ред рдпрд╣ рдореЗрд░рд╛ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╡рд┐рдХрд▓реНрдк https://github.com/pypa/pip/issues/6162 рдФрд░ рдбрд┐рдкреЗрдВрдбреЗрдВрд╕реА_рд▓рд┐рдВрдХ рдХрд╛ рдбрд┐рдкреНрд░реЗрд╢рди рд╣реИред
рд╣рдо рдПрдХ рдирд┐рдЬреА рд░реЗрдкреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдФрд░ рд╣рдорд╛рд░рд╛ рдЕрдкрдирд╛ рдЖрдВрддрд░рд┐рдХ рд╕рд░реНрд╡рд░ рдирд╣реАрдВ рд╣реИред рд╣рдорд╛рд░рд╛ рд╕рдорд╛рдзрд╛рди s3 рдХреЗ рд▓рд┐рдП рдкреИрдХреЗрдЬ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдирд╛ рд╣реИ рдФрд░ рдлрд┐рд░ рдЙрдиреНрд╣реЗрдВ рдЙрдкрднреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдо рдЙрдиреНрд╣реЗрдВ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рддреЗ рд╣реИрдВ, рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕реНрдерд╛рдиреАрдп рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдбрд╛рд▓рддреЗ рд╣реИрдВ, рдлрд┐рд░ рдЙрдиреНрд╣реЗрдВ install_requires
рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред
рдореБрдЭреЗ рдпрдХреАрди рд╣реИ рдХрд┐ рдХрдИ рдЕрдиреНрдп рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рд╣реИрдВ рдЬреЛ рд╕реНрдерд╛рдиреАрдп рдкреИрдХреЗрдЬреЛрдВ рдХреЛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╣рдЬ рддрд░реАрдХреЗ рд╕реЗ рд▓рд╛рднрд╛рдиреНрд╡рд┐рдд рд╣реЛрдВрдЧреЗред
@ryanaklein рдореИрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рджреВрдВрдЧрд╛ рдФрд░ рдЙрдиреНрд╣реЗрдВ
S3 рдХреЗ рдиреЗрдЯрд╡рд░реНрдХ / $ $ рд▓рд╛рдЧрдд рдореЗрдВ рдХрдЯреМрддреА рд╣реЛ рд╕рдХрддреА рд╣реИ :)
рдЕрдкреЗрдХреНрд╖рд┐рддреН рд╡реНрдпрд╡рд╣рд╛рд░
рдореБрдЭреЗ рдЕрдкрдиреЗ рдХреЛрдбрдмреЗрд╕ рдкрд░ рд╕реНрдерд╛рдиреАрдп рд╢реНрд░реЗрдгреА рдХреЗ рдкреИрдХреЗрдЬ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПname @ ./some/path
(рдпрд╛, рдИрдорд╛рдирджрд╛рд░реА рд╕реЗ, рдХреЗрд╡рд▓./some/path
) рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
рдкреНрд░рддреНрдпрдХреНрд╖ URL рд╕рдВрджрд░реНрдн рдХреЗ рд▓рд┐рдП ( name @ ./some/path
) рджреЛ рд╕реНрдерд╛рди рд╣реИрдВ рдЬрд╣рд╛рдВ рдХрд╛рдо рд╣реЛ рд░рд╣рд╛ рд╣реИ:
рдмрд╛рдж рд╡рд╛рд▓реЗ рдкреАрдИрдкреА 508 рдХреЗ рдЕрдиреБрд╕рд╛рд░ рд╕реНрд╡реАрдХрд╛рд░реНрдп рдирд╣реАрдВ рд╣реЛрдВрдЧреЗ, рдЗрд╕рд▓рд┐рдП рд╕рднреА рдЙрдкрдХрд░рдгреЛрдВ рдкрд░ рдХрд╛рдо рдХрд░рдирд╛ рдХрдо рд╕рдорд░реНрдерди рдХрд╛ рдФрдЪрд┐рддреНрдп рд╕рд╛рдмрд┐рдд рдХрд░рдирд╛ рдХрдард┐рди рд╣реЛрдЧрд╛ред
рдпрд╣ рдЕрд╕реНрдкрд╖реНрдЯ рдФрд░ рд╕рдордп рдмрд░реНрдмрд╛рдж рдХрд░рдиреЗ рд╡рд╛рд▓реА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рдмреБрд░рд╛ UX рдорд┐рд╢реНрд░рд┐рдд рд╣реИред
рд╣рдо рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдХреЛ рдХреИрд╕реЗ рд╕реБрдзрд╛рд░ рд╕рдХрддреЗ рд╣реИрдВ?
рдКрдкреНрд╕! рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐, рдЬрдм рд╣рдо рдкрд╣рд▓реЗ рдкрд╛рд░реНрд╕ рдХреЙрд▓ рд╕реЗ "рдЕрдирдкреЗрдХреНрд╖рд┐рдд" рдкрд░рд┐рдгрд╛рдо рджреЗрддреЗ рд╣реИрдВ, рддреЛ рд╣рдорд╛рд░рд╛ рдкрде рдкреВрд░реНрдг рдлрд╝рд╛рдЗрд▓ рдмрди рдЬрд╛рддрд╛ рд╣реИ: /// ...
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ 22852 рдЕрдВрдХ рдореЗрдВ рдЙрдард╛рдП рдЧрдП - "urllib.parse рдЧрд▓рдд рддрд░реАрдХреЗ рд╕реЗ рдЦрд╛рд▓реА #fragment рд╕реНрдЯреНрд░рд┐рдкреНрд╕? рдХреНрд╡реЗрд░реА; // netloc"
рдпрд╣ рдмрдЧ # 3783 рднреА рдЬрд╛рд░реА рдХрд░рддрд╛ рд╣реИ - рдЗрд╕ рдЯрд┐рдкреНрдкрдгреА рдХреЛ рджреЗрдЦреЗрдВред
рдЗрд╕ рдореБрджреНрджреЗ рдХреА рд╕реНрдерд┐рддрд┐ рдХреНрдпрд╛ рд╣реИ? рд╕реНрдерд╛рдиреАрдп рдирд┐рд░реНрднрд░рддрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдорд╛рдзрд╛рди рдЬреЛ PyPI рдкрд░ рдирд╣реАрдВ рд╣реИ, рдХреА рддрддреНрдХрд╛рд▓ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдЕрдЦрдВрдб рд╕рдВрд╡рд╣рдиреА рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВред
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ npm рдиреЗ рдПрдХ рд╕рдорд╛рди рддрд░реАрдХреЗ рд╕реЗ рдЗрд╕ рд╕реБрд╡рд┐рдзрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рд╣реИ рдФрд░ dependencies
рд╕реНрдерд╛рдиреАрдп рдкрде рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ package.json
рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ ред
рдХреГрдкрдпрд╛ рдпрд╣ рдЬрд╛рдирдиреЗ рдХреЗ рд▓рд┐рдП
рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА
рдареАрдХ рд╣реИ, рдореИрдВ рд╕рдорд╕реНрдпрд╛ рджреЗрдЦрддрд╛ рд╣реВрдВред
setuptools
,pkg-resources
рдФрд░pip
рд╕рднреАpackaging
рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рдереЛрдбрд╝реЗ рдЕрд▓рдЧ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВредpip
, рдпрд╣ рд╡рд╣ рд╕рдВрд╕реНрдХрд░рдг рд╣реИ рдЬреЛ рдореИрдВрдиреЗ рдКрдкрд░ рджрд┐рдЦрд╛рдпрд╛ рдерд╛редрд╣рд╛рд▓рд╛рдБрдХрд┐, рдмрд╛рдХреА рд╕рдм рдореЗрдВ, рдпрд╣ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реИ (рдореБрдЭреЗ рдпрдХреАрди рдирд╣реАрдВ рд╣реИ рдХрд┐ "рдирдпрд╛" рдПрдХ рд╣реИ, рд▓реЗрдХрд┐рди рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рддрд░реНрдХ рдмрд╣реБрдд рд╕реАрдорд┐рдд рд╣реИ рдФрд░ RFC 3986 рдХреЗ рдЕрдиреБрд╕рд╛рд░
file:///
рдЕрдиреБрд╕рд╛рд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрдиреБрдкрд╛рд▓рди рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдПрдХ рдЦрд╛рд▓реАnetloc
):ЁЯЩД
рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЬрдм рд╕реЗ рдореЗрд░реА рдлрд╝рд╛рдЗрд▓рдкрде рдореЗрдВ
file:///foo/bar
рдФрд░file://localhost/foo/bar
рддрдм рддрдХ рдпрд╣ рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИредрдпрд╣рд╛рдБ рдкреВрд░рд╛ рд╕рдорд╛рдзрд╛рди рд╣реИ :
рдпрд╣ рдЕрд╕реНрдкрд╖реНрдЯ рдФрд░ рд╕рдордп рдмрд░реНрдмрд╛рдж рдХрд░рдиреЗ рд╡рд╛рд▓реА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдмрд╣реБрдд рдмреБрд░рд╛ UX рдорд┐рд╢реНрд░рд┐рдд рд╣реИред
рд╣рдо рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдХреЛ рдХреИрд╕реЗ рд╕реБрдзрд╛рд░ рд╕рдХрддреЗ рд╣реИрдВ?