์ด๊ฒ์ #444์์ ์ ๊ธฐ๋์์ง๋ง ์ด ์ฝ๋ ๋ Python 3.4.1์์ ํญ์ b'/'
ํ๊ฐ๋๋ฏ๋ก ์ฌ๋์๋ ์ฌ์ ํ ์ด์ค์ผ์ดํ๋์ง ์์ต๋๋ค.
๊ทธ๋ฅ ์กฐ์ฌ @mitsuhiko
์ด์ ๋ ๋ชจ๋ฅด๊ฒ ์ง๋ง do_urlencode
์ฌ์ ํ ์ฌ๋์๋ฅผ ์ด์ค์ผ์ดํํ์ง ์๋ ๋ฐ๋ฉด unicode_urlencode
๋ ์์๋๋ก ์๋ํฉ๋๋ค.
Python 3.4.3 (default, Oct 14 2015, 20:28:29)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import jinja2
>>> jinja2.utils.unicode_urlencode("http://url.by", for_qs=True)
'http%3A%2F%2Furl.by'
>>> jinja2.filters.do_urlencode("http://url.by")
'http%3A//url.by'
>>> jinja2.__version__
'2.9.dev'
urlencode
ํํฐ๋ ์ฌ๋์๋ฅผ ์ด์ค์ผ์ดํํ์ง ์๊ธฐ ๋๋ฌธ์
๋๋ค. ๊ผญ ๊ทธ๋์ผ ํ๋ ํน๋ณํ ์ด์ ๊ฐ ์๋์? ์ด๊ฒ์ ๋ช
ํํ ํ๊ธฐ ์ํด: ์ ๋ฌ๋ ํค/๊ฐ ์์ ๊ฐ ์์น์์ ์ฌ๋์๋ง ์ธ์ฝ๋ฉํฉ๋๋ค.
์ด๊ฒ์ด URL ์ธ์ฝ๋ฉ์ ์ํ ๊ธฐ๋ฅ์ ํ์ค ๋์์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. http://meyerweb.com/eric/tools/dencoder/ ์ ๊ฐ์ ๋๊ตฌ๋ ์ด๋ฌํ ๋ฐฉ์์ผ๋ก ์๋ํฉ๋๋ค. ๋ํ ์ด์ค์ผ์ดํ ์ฒ๋ฆฌ๋ ์ฌ๋์๊ฐ ์๋ GET ์์ฒญ ๋ด๋ถ์ URL์ด ์ ๋ฌ๋ ๊ฒ์ผ๋ก ์์ํ๋ ํ์ฌ ๋ด๋ถ์ ํ๋ ์ด์์ ๋๊ตฌ๊ฐ ์์ต๋๋ค.
๋ํ, ๋๋ ์ดํดํ์ง ์๋ ์ด์ unicode_urlencode
๋ผ๋ ๋ด๋ถ do_urlencode
์ for_qs=True
.
์ ๊ฐ ๋ญ๊ฐ ์๋ชป ์ดํดํ๊ณ ์๋ ๊ฒ์ผ ์๋ ์์ต๋๋ค.
์ฌ๋์๋ ๊ฒฝ๋ก ๊ตฌ์ฑ ์์์ ์์ฝ๋ ๋ฌธ์์ด๋ฉฐ ๋ ์ผ๋ฐ์ ์ธ ๋์์ URL ์ธ์ฝ๋ฉ ๋์์ ๊ฐ์ ํ ๋ ์ฌ๋์๋ฅผ ์ ์ธํ ๋ชจ๋ ๊ฒ์ ์ธ์ฝ๋ฉํ๋ ๊ฒ์
๋๋ค. (์ฌ๋์๋ฅผ %2f
๋ก ์ธ์ฝ๋ฉํ๋) ๋์์ ๋ฐฑ์๋ ์๋ฒ๊ฐ ์ผ๋ฐ์ ์ผ๋ก %2f
๋ฐ /
๋ฅผ ๊ตฌ๋ณํ ์ ์๊ธฐ ๋๋ฌธ์ ๋ณด์ ๋ฌธ์ ๋ก ์ธํด ๋๋ถ๋ถ์ ์๋ฒ๊ฐ ์ด๋ฌํ ์์ฒญ์ ์์ ํ ๊ฑฐ๋ถํ๊ธฐ ๋๋ฌธ์ ์๋ฏธ๊ฐ ์์ต๋๋ค. ๋์ฝ๋ฉ๋ ์ฅํ
์์ ์๋ํ ๋ ๊ฒฝ๋ก ๊ตฌ์ฑ ์์.
๋ฐ๋ผ์ ์ฌ๋์๊ฐ ์ค์ ๋ก ์ธ์ฝ๋ฉ์ด ์๋ฏธ๊ฐ ์๋ ์ ์ผํ ๋ถ๋ถ์ ์ฟผ๋ฆฌ ๋ฌธ์์ด์ ์์ผ๋ฉฐ ์ฌ๊ธฐ์์ urlencode
์ dict ๊ธฐ๋ฐ ์ธ์ฝ๋๊ฐ ๊ทธ๋ ๊ฒ ์๋ํฉ๋๋ค. ๊ทธ๋ฌ๋ ์ฌ๋์๊ฐ ์์ด๋ ์ธ์ฝ๋ฉํ ํ์๊ฐ ์์ผ๋ฏ๋ก ์ธ์ฝ๋ฉ์ ๊ฐ์ ํ ์ด์ ๊ฐ ์์ต๋๋ค.
urlencode
ํจ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋๋ถ๋ถ์ ์ฌ๋๋ค์๊ฒ ์ฌ์ฉํด์ผ ํ๋ฏ๋ก ์ฌ๋์๋ฅผ ์ธ์ฝ๋ฉํ์ง ์์ต๋๋ค. ์ฌ์ฉ์ ์ ์ ์๊ตฌ ์ฌํญ์ด ์๋ ๊ฒฝ์ฐ ํํฐ ๋ฑ๋ก์์ ๊ธฐ๋ฅ์ ์ฌ์ ์ํ ์ ์์ต๋๋ค.
ํ์ธ. ์๋ฅด๋ฏผ ๊ฐ์ฌํฉ๋๋ค.
์๋ ํ์ธ์, ์ฌ๋์ ๊ฑฐ๋ถ์ ๋์ผํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค. ์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
jinja2.Template("{{ ๋์คํฌ|๊ฑฐ๋ถ('sameas', '/')|๋ชฉ๋ก }}").render(disks=["/", "/mnt/disk0", "/mnt/disk1"])
์ "['/', '/mnt/disk0', '/mnt/disk1']"
๋ฃจํธ ๋์คํฌ๋ฅผ ๊ฑฐ๋ถํ๊ณ ์ถ์ง๋ง ๋ ์ด์ ์๋ํ์ง ์์ต๋๋ค. ํด๊ฒฐ ๋ฐฉ๋ฒ์ ๋ฌด์์ ๋๊น?
>>> import jinja2
>>> jinja2.Template("{{ disks|reject('sameas', '/')|list }}").render(disks=["/", "/mnt/disk0", "/mnt/disk1"])
u"['/mnt/disk0', '/mnt/disk1']"
>>> jinja2.__version__
Out[3]: '2.8'
๋๋ฅผ ์ํด ์๋ํฉ๋๋ค.
@ThiefMaster๊ฐ ์ฌ์ ํ ์๋ํ์ง ์์ต๋๋ค. ํ์ด์ฌ ๋ฌธ์ ๊ฐ ์์ต๋๊น? ์ฌ์ฉํ ํ์ด์ฌ ๋ฒ์ ์ด ๋ฌด์์ ๋๊น?
Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import jinja2
>>> jinja2.Template("{{ disks|reject('sameas', '/')|list }}").render(disks=["/", "/mnt/disk0", "/mnt/disk1"])
u"['/', '/mnt/disk0', '/mnt/disk1']"
>>> jinja2.__version__
'2.8'
์ค.. sameas
๋ is
( 'foo' is 'foo'
๊ฐ ์๋ํ ๊ฒ์ด๋ผ๊ณ ๊ธฐ๋ํ ์๋ ์์ต๋๋ค). ๋น์ ์ด ์ํ๋ equalto
์ฌ์ฉํ๋ ==
.
์, ์๋ํฉ๋๋ค. ์ ๋ Jinja2์ ๊ฐ์กฑ์ด ์๋๋๋ค. @ThiefMaster ๊ฐ์ฌํฉ๋๋ค.
๋ฐ๋ผ์ ์ฌ๋์๊ฐ ์ค์ ๋ก ์๋ฏธ ์๋ ์ธ์ฝ๋ฉ์ด ๋๋ ์ ์ผํ ๋ถ๋ถ์ ์ฟผ๋ฆฌ ๋ฌธ์์ด์ ์์ผ๋ฉฐ urlencode๊ฐ ๊ฐ์ง๊ณ ์๋ dict ๊ธฐ๋ฐ ์ธ์ฝ๋๊ฐ ๊ทธ๋ ๊ฒ ์๋ํ๋ ๊ณณ์ ๋๋ค. ๊ทธ๋ฌ๋ ์ฌ๋์๊ฐ ์์ด๋ ์ธ์ฝ๋ฉํ ํ์๊ฐ ์์ผ๋ฏ๋ก ์ธ์ฝ๋ฉ์ ๊ฐ์ ํ ์ด์ ๊ฐ ์์ต๋๋ค.
์๋์, ์๋ฅผ ๋ค์ด ์ฌ์ฉ์ ์ด๋ฆ๊ณผ ๋น๋ฐ๋ฒํธ์๋ /
๋ฅผ ์ธ์ฝ๋ฉํด์ผ ํฉ๋๋ค.
์ด๊ฒ์ด JS์ encodeURI __and__ encodeURIComponent ๊ฐ ์๋ ์ด์ ์
๋๋ค.
๊ทธ๊ฒ์ ์ถฉ๋ถํ ๊ณตํํ์ง๋ง ์ค์ ๋ก๋ ํ์ํ์ง ์์ผ๋ฉฐ ํฌํจ ๋ ์๊ฒฉ ์ฆ๋ช ์ ์ด์จ๋ ์ฌ์ฉ๋์ง ์์ต๋๋ค. ํ ํ๋ฆฟ ๋ด์์ ์์ฑ๋ ๊ฐ๋ฅ์ฑ์ด ๋ฎ๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก ๊ณ ๋ คํ ๊ฐ์น๊ฐ ์๋ ๊ฒฝ์ฐ์ ๋๋ค.
Ansible์ Jinja๋ฅผ ์ฌ์ฉํ๋ฉฐ ์์คํ
์ ์ค์ ํ ๋ ๋ณด์ ์๊ฒฉ ์ฆ๋ช
์ ์ฒ๋ฆฌํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์
๋๋ค. ๋ฐฉ๊ธ ์๋์ผ๋ก ์์ฑ๋ ๋น๋ฐ๋ฒํธ์ ์ฌ๋์๊ฐ ํฌํจ๋์ด ์๋๋ฐ ์ด ์ฌ๋์๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค URL์ ์์ฑํ๊ธฐ ์ํด urlencode
๋ก ๋์ฒด๋์ง ์์ ๊ฒฝ์ฐ์
๋๋ค. ์ด๋ ๋งค์ฐ ๋ถํํ ์ผ์
๋๋ค. ํ์ฌ ๋์์ ๊นจ๋ ๊ฒ์ด ๋ฌธ์ ๊ฐ ๋ ์ ์์ง๋ง ์ฌ๋์๋ฅผ ์ด์ค์ผ์ดํํ์ง ์๋ ๋ ๋ฒ์งธ ํํฐ๋ฅผ ๋์
ํ์ง ์๊ฒ ์ต๋๊น?
์ค์๋ธ์ ๊ทธ๋ ๊ฒ ํ ์ ์์ต๋๋ค. Jinja ์์ฒด์๋ ๊ทธ๋ฌํ ๋ณ๊ฒฝ์ด ํ์ํ์ง ์์ต๋๋ค. ์ฌ์ฉ์ ์ ์ ํํฐ๋ฅผ ์ถ๊ฐํ๊ฑฐ๋ ๋ด์ฅ ํํฐ๋ฅผ ๊ต์ฒดํ ์ ์์ ์ ๋๋ก ์ถฉ๋ถํ ํ์ฅ ๊ฐ๋ฅํฉ๋๋ค.
@ThiefMaster Jinja ์์ฒด์ ํฌํจํ๋ ๊ฒ์ด ์ ์ฉํ์ง ๊ฒฐ์ ํ ๋ HTML ํ ํ๋ฆฟ์ ๊ตฌ์ฑํ๋ ๊ฒ ์ด์ธ์ ์ฌ์ฉ ์ฌ๋ก๋ ๊ด๋ จ์ด ์์ต๋๊น? ์๋ฅผ ๋ค์ด, Ansible๊ณผ ์ ์ฌํ ๋ชฉ์ ์ ๊ฐ์ง Saltstack ํ๋ก์ ํธ๋ ํ ํ๋ฆฟ์ Jinja๋ฅผ ์ฌ์ฉํ๋ฉฐ ๋์ผํ ๋ณ๊ฒฝ์ ์ด์ ์ ์ป์ ์ ์์ต๋๋ค.
@danielkza saltstack ์ด ํํฐ๋ฅผ ์ ๊ณตํ๋ ๊ฒ์
@mitsuhiko ์ Jinja์ ๋ด์ฅ ํํฐ๊ฐ ํฌํจ๋์ด ์์ต๋๊น? ์ฌ๋ฌ ์ฌ์ฉ ์ฌ๋ก์์ ์ ์ฉํ๊ธฐ ๋๋ฌธ์ด๋ผ๊ณ ์ถ์ธกํ ์ ์์ต๋๋ค. URL์์ ์ฌ๋์๋ฅผ ์ด์ค์ผ์ดํํ ์ ์๋ ๊ฒ์ด ๋ฐ๋์งํ ๋ ๊ฐ์ง ์๋ก Ansible๊ณผ Salt๋ฅผ ์ฌ์ฉํ์ต๋๋ค. ๋ฐ๋ผ์ ๋ชจ๋ ์ฌ๋์ด ์ฌ์ฉํ ์ ์๋๋ก ํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
safe
์ธ์๋ฅผ urlencode
์ ์ถ๊ฐํ๋ ๊ฒ์ Python์ urllib.url_quote
์ฒ๋ผ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ๋์๊ฐ ์ ์ง๋์ง๋ง ์ฝ๊ฒ ๋ฌด์ํ ์ ์๋ ๋ฐฉ์์ผ๋ก ์ถ๊ฐํ๋ ๊ฒ์
๋๋ค.
Jinja๋ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ ๋ช ๊ฐ์ง ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ค๊ณ ํฉ๋๋ค. ์ฝ 95%๋ฅผ ์ป์ ์ ์๋ urlencoding์ ์ํ ๋ ๊ฐ์ง ๋ชจ๋๊ฐ ์์ต๋๋ค. ์ฌ์ ์ ์ธ์ฝ๋ฉํ์ฌ ์ ์ฒด ์ฟผ๋ฆฌ ๋ฌธ์์ด์ ์ธ์ฝ๋ฉํ ์ ์์ผ๋ฉฐ ๋ฌธ์์ด์ urlencode๋ฅผ ํตํ ๊ฒฝ๋ก์ ์ ํจํ ๊ณตํต ์งํฉ์ผ๋ก ์ธ์ฝ๋ฉํ ์ ์์ต๋๋ค.
์ฐ๋ฆฌ๋ utf-8์ด๋ ๊ทธ ์ธ์๋ ์๋ฌด๊ฒ๋ ํ์ง ์์ต๋๋ค. ์ด๋์์ ๋ฉ์ถ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค. URL์ ๋๋ฌด ๋ง์ ๋ถ๋ถ์ด ์๊ณ ํ์ฑ๊ฐ ์์ผ๋ฉฐ ๋ชจ๋ ๊ณ ์ ํ ๊ผฌ์์ด ์์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ๊ฑฐ๊ธฐ์ ์์ ๋ netloc์ฉ ํจ๋์ฝ๋ ์ธ์ฝ๋๋ ์ ๊ณตํ์ง ์๋ ์ด์ ๋ ๋ฌด์์ ๋๊น?
API ํธ์ถ์ ํตํด gitlab ๋ฆฌํฌ์งํ ๋ฆฌ์ ํ์ผ์ ๋ง๋ค๋ ค๊ณ ํ ๋ ์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค. gitlab API๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์ฌ๋์๋ฅผ ์ธ์ฝ๋ฉํด์ผ ํฉ๋๋ค. ์ด ์์ ์ ์ํํ๋ ค๋ฉด ๋ค์์ ์ํํฉ๋๋ค. {{ myvar | urlencode | regex_replace('/','%2F') }}. ํ๋ ์ด๋ถ ์์ ์์ Ansible ๋ฐ Jinja2 ํํฐ๋ก ์์ ํ๊ณ ์์ต๋๋ค. ์ด๊ฒ์ ๋ด๊ฐ ์๋ํ๋ ๊ฒ์ ํ์ธํ๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ์น๋ ์ฌ๋๋ค์ ์ํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ๋ ์ ์์ต๋๋ค.
์ด๋ค ๋ฌธ์๋ฅผ ๋ฐฑ๋ถ์จ๋ก ์ธ์ฝ๋ฉํด์ผ ํ๋์ง์ ๋ํ ์ฝ๊ฐ์ ๋ ผ์์ด ์์ต๋๋ค. ์ด ๋ด์ฉ์ ํ์ฌ RFC3986์์ ๋ค๋ฃจ๊ณ ์์ต๋๋ค. https://tools.ietf.org/html/rfc3986#section -2.2
๋ด ์ฌ์ฉ ์ฌ๋ก์ ๊ฒฝ์ฐ @ahuffman ์ด ํฉ๋ฆฌ์ ์ธ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ ๊ณตํ์ต๋๋ค.
๋ ๋์์ผ๋๊น ๋ซ๊ณ ์ถ์ด์. ์ด๊ฒ์ ๋ํ ๋์ ์ฃผ์ฅ์ ์ด๋ฏธ ์ฌ๊ธฐ์์ ์ด๋ฏธ ์ธ๊ธ๋์์ง๋ง GitLab์ API์ ๋์์ด ๋๋๋ก ๋ค๋ฅธ ํํฐ๋ฅผ ์ถ๊ฐํ ๊ฒ์ ์ ์ํ๋ ํ์ฌ PR์ด ์ด๋ ค ์๊ธฐ ๋๋ฌธ์ ๋ค์ ๊ฐ์กฐํ๊ณ ์ถ์ต๋๋ค(#864).
๋ชจ๋ ์ข ๋ฅ์ ํ๋ก์ ์ค์ ๋ค์ ๋ฐฐ์น๋๊ณ ์ด์ ๋ํด ์ด๋ ค ์๋ ๋ฌธ์ ๊ฐ ์๋ ๊ฒฝ์ฐ GitLab์ API๊ฐ ์์๋์์ต๋๋ค( ์์ ๋ฌธ์ ). ๋์ ํด๊ฒฐ ๋ฐฉ๋ฒ๊ณผ ์ฌ๋๋ค์ด ํ์ง ๋ง์์ผ ํ๋ ์ด์ ๋ฅผ ๋ฌธ์ํํ ๊ฒ์ ์ ์ํฉ๋๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
{{ value|urlencode|replace("/", "%2f") }}
์ด๊ฒ์ ์ฝ๊ฐ์ ์ ์ฅ์ ์ทจํ๋ ๊ฒ์ด์ง๋ง ์ด๋ ๊ฒ ํ๋ฉด ์ฌ๋๋ค์ด ์ด์ ์ ์์๋ ๋ค๋ฅธ ์ฌ๋๋ค์ ์ค์๋ฅผ ๋ฐ๋ณตํ์ง ์๋๋ก ๊ฒฉ๋ คํ ์ ์์ต๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
API ํธ์ถ์ ํตํด gitlab ๋ฆฌํฌ์งํ ๋ฆฌ์ ํ์ผ์ ๋ง๋ค๋ ค๊ณ ํ ๋ ์ด ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค. gitlab API๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์ฌ๋์๋ฅผ ์ธ์ฝ๋ฉํด์ผ ํฉ๋๋ค. ์ด ์์ ์ ์ํํ๋ ค๋ฉด ๋ค์์ ์ํํฉ๋๋ค. {{ myvar | urlencode | regex_replace('/','%2F') }}. ํ๋ ์ด๋ถ ์์ ์์ Ansible ๋ฐ Jinja2 ํํฐ๋ก ์์ ํ๊ณ ์์ต๋๋ค. ์ด๊ฒ์ ๋ด๊ฐ ์๋ํ๋ ๊ฒ์ ํ์ธํ๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ์น๋ ์ฌ๋๋ค์ ์ํ ํด๊ฒฐ ๋ฐฉ๋ฒ์ด ๋ ์ ์์ต๋๋ค.