λ΄κ° μ₯κ³ λ₯Ό μ¬μ© django_extensions
νλ μ©λ μ¬μ©νλ κ²½μ° λλ²κΉ
WERKZEUG runserver_plus
. Werkzeugλ Python3μ μ¬μ©ν λ λ€μ μμΆμ μ μ¬μ©νμ¬ get_content_type()
μμ νλ°νλ κ² κ°μ΅λλ€.
Traceback (most recent call last):
File "/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py", line 177, in run_wsgi
execute(self.server.app)
File "/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py", line 165, in execute
application_iter = app(environ, start_response)
File "/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/debug/__init__.py", line 173, in __call__
response = self.get_resource(request, arg)
File "/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/debug/__init__.py", line 154, in get_resource
return Response(f.read(), mimetype=mimetype)
File "/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/wrappers.py", line 749, in __init__
mimetype = get_content_type(mimetype, self.charset)
File "/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/utils.py", line 224, in get_content_type
if mimetype.startswith('text/') or \
TypeError: startswith first arg must be bytes or a tuple of bytes, not str
λ¬Έμ λ₯Ό ν΄κ²°νλ PR μ μΆ
μ΄κ²μ΄ Werkzeugμ μλͺ»μΈμ§ Djangoκ° μλ΅μ μλͺ»λ λ¬Έμμ΄ μ νμ μ¬μ©νλμ§ νμ€νμ§ μμ΅λλ€.
λ€μμ ipdbμ μ 체 μμΆμ μ΄λ©° Djangoκ° μ΄λμμλ νΈμΆλλ κ²μ λ³Ό μ μμ΅λλ€. μμ ν stackstaceλ werkzeugμλ§ μλ κ² κ°μ΅λλ€.
ipdb> w
/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py(692)inner()
690 make_server(hostname, port, application, threaded,
691 processes, request_handler,
--> 692 passthrough_errors, ssl_context).serve_forever()
693
694 if os.environ.get('WERKZEUG_RUN_MAIN') != 'true':
/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py(436)serve_forever()
434 self.shutdown_signal = False
435 try:
--> 436 HTTPServer.serve_forever(self)
437 except KeyboardInterrupt:
438 pass
/usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/socketserver.py(238)serve_forever()
236 poll_interval)
237 if self in r:
--> 238 self._handle_request_noblock()
239
240 self.service_actions()
/usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/socketserver.py(305)_handle_request_noblock()
303 if self.verify_request(request, client_address):
304 try:
--> 305 self.process_request(request, client_address)
306 except:
307 self.handle_error(request, client_address)
/usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/socketserver.py(331)process_request()
329
330 """
--> 331 self.finish_request(request, client_address)
332 self.shutdown_request(request)
333
/usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/socketserver.py(344)finish_request()
342 def finish_request(self, request, client_address):
343 """Finish one request by instantiating RequestHandlerClass."""
--> 344 self.RequestHandlerClass(request, client_address, self)
345
346 def shutdown_request(self, request):
/usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/socketserver.py(669)__init__()
667 self.setup()
668 try:
--> 669 self.handle()
670 finally:
671 self.finish()
/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py(200)handle()
198 rv = None
199 try:
--> 200 rv = BaseHTTPRequestHandler.handle(self)
201 except (socket.error, socket.timeout) as e:
202 self.connection_dropped(e)
/usr/local/Cellar/python3/3.4.2_1/Frameworks/Python.framework/Versions/3.4/lib/python3.4/http/server.py(398)handle()
396 self.close_connection = 1
397
--> 398 self.handle_one_request()
399 while not self.close_connection:
400 self.handle_one_request()
/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py(235)handle_one_request()
233 self.close_connection = 1
234 elif self.parse_request():
--> 235 return self.run_wsgi()
236
237 def send_response(self, code, message=None):
/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py(177)run_wsgi()
175
176 try:
--> 177 execute(self.server.app)
178 except (socket.error, socket.timeout) as e:
179 self.connection_dropped(e, environ)
/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/serving.py(165)execute()
163
164 def execute(app):
--> 165 application_iter = app(environ, start_response)
166 try:
167 for data in application_iter:
/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/debug/__init__.py(173)__call__()
171 frame = self.frames.get(request.args.get('frm', type=int))
172 if cmd == 'resource' and arg:
--> 173 response = self.get_resource(request, arg)
174 elif cmd == 'paste' and traceback is not None and \
175 secret == self.secret:
/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/debug/__init__.py(154)get_resource()
152 f = open(filename, 'rb')
153 try:
--> 154 return Response(f.read(), mimetype=mimetype)
155 finally:
156 f.close()
/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/wrappers.py(749)__init__()
747 mimetype = self.default_mimetype
748 if mimetype is not None:
--> 749 mimetype = get_content_type(mimetype, self.charset)
750 content_type = mimetype
751 if content_type is not None:
> /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/utils.py(224)get_content_type()
222 # charset = charset.decode('utf-8')
223 import ipdb; ipdb.set_trace()
--> 224 if mimetype.startswith('text/') or \
225 mimetype == 'application/xml' or \
226 (mimetype.startswith('application/') and
ipdb> type(mimetype), type(charset)
(<class 'bytes'>, <class 'str'>)
λ¬Έμ λ μμ 2κ° νλ μμ μλ κ² κ°μ΅λλ€.
ipdb> up
> /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/wrappers.py(749)__init__()
748 if mimetype is not None:
--> 749 mimetype = get_content_type(mimetype, self.charset)
750 content_type = mimetype
ipdb> up
> /Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/debug/__init__.py(154)get_resource()
153 try:
--> 154 return Response(f.read(), mimetype=mimetype)
155 finally:
ipdb> l
149 if isfile(filename):
150 mimetype = mimetypes.guess_type(filename)[0] \
151 or 'application/octet-stream'
152 f = open(filename, 'rb')
153 try:
--> 154 return Response(f.read(), mimetype=mimetype)
155 finally:
156 f.close()
157 return Response('Not Found', status=404)
158
159 def __call__(self, environ, start_response):
ipdb> mimetypes.guess_type(filename)[0]
b'text/javascript'
μ΄μν μ μ guess_type
κ° λ°μ΄νΈ λ λ¬Έμμ΄μ λ°ννλ€λ κ²μ
λλ€. μμμ λμΌν νμΌμ μ νμ μΆμΈ‘νλ €κ³ ν λ λ¬Έμμ΄μ΄ νμλ©λλ€.
>>> mimetype = mimetypes.guess_type('/Volumes/Data/Users/miki725/.virtualenvs/test-py3/lib/python3.4/site-packages/werkzeug/debug/shared/jquery.js')[0]
>>> type(mimetype)
<class 'str'>
get_content_type()
λμ μ¬κΈ°μμ mimetypeμ λ³ννλλ‘ PRμ μ‘°μ ν΄μΌ ν©λκΉ?
μ΄μν μ μ guess_typeμ΄ λ°μ΄νΈ λ λ¬Έμμ΄μ λ°ννλ€λ κ²μ λλ€.
κ·νμ PRμ λ¬Έμ λ₯Ό ν΄κ²°νμ§λ§ κ·νκ° λ§νλ―μ΄ μ΄λ° μΌμ΄ λ°μν΄μλ μλ©λλ€.
guess_type
νΈμΆμ΄ λ°μνλ νλ μμ νμΌ μ΄λ¦μ 무μμ
λκΉ?
λ¬Έμμ΄. μλ§λ guess_type
λ νμΌ μ΄λ¦κ³Ό λμΌν μ νμ λ°ννμ§λ§ λΆλͺ
ν κ·Έλ μ§λ μμ΅λλ€.
μλ
νμΈμ, μμ κ°μ΄ django-extensions
ν¨ν€μ§λ₯Ό μ¬μ©ν λ μμ£Ό λ°μν©λλ€. κ±°μ 2λ
λμ 건λλ¦° μ μ΄ μλλ° μ°κ²°λ MRμ λ³ν©νλ λ° λ¬Έμ κ° μμ΅λκΉ?
μ΅κ·Όμ κ°μ λ¬Έμ κ° λ°μνμ΅λλ€. μ μκ²λ μλ° μ€ν¬λ¦½νΈ νμΌμμ λ°μν©λλ€. λλ²κΉ
ν λ΄ λ¬Έμ κ° django-pipelineμ΄λΌλ κ²μ λ°κ²¬νμ΅λλ€. types_map
μμ νκ³ λ€μμ μ€μ ν©λλ€. https://github.com/jazzband/django-pipeline/blob/master/pipeline/conf.py#L81 -L87 μ¬κΈ° https://github.com/jazzband/django-pipeline/blob/master/pipeline/utils.py#L42 -L43 .. :S :S ... ν΄κ²°νλ €λ©΄ νμ΄νλΌμΈ μ€μ μμ MIMETYPESλ₯Ό μ¬λ°λ₯΄κ² μ€μ ν΄μΌ νμ΅λλ€. .
PR λ³ν©μ μ¬κ³ ν΄μΌ ν μλ μμ΅λλ€.
μ΄κ²μ΄ λκ΅°κ°μκ² λμμ΄ λκΈ°λ₯Ό λ°λλλ€... ν볡ν λλ²κΉ !
Django-Pipelinesλ mimetype μ ν 맡μ λ°μ΄νΈλ₯Ό λ£μ§ μλλ‘ μμ λμ΄μΌ ν©λλ€. Django-Extensionsλ μ무 μμ λ μννμ§ μλ κ²μΌλ‘ 보μ΄μ§λ§ μ΄λ λ€λ₯Έ μ’ μμ±μ΄ μ€μλνκ³ μμμ μλ―Έν©λλ€. λμ λ°μ΄ν°λ₯Ό μΆκ°νλ λΌμ΄λΈλ¬λ¦¬μμ ν΄κ²°ν΄μΌ νλ€κ³ μκ°νμ¬ μ΄κ²μ λ«μ΅λλ€. λκ΅°κ°κ° mimetypes μ ν 맡μμ λ°μ΄νΈλ₯Ό μμν΄μΌ νλ ν©λΉν μ΄μ λ₯Ό κ²μν μ μλ€λ©΄ μ¬κ³ νκ² μ΅λλ€.
κ°μ₯ μ μ©ν λκΈ
μλ νμΈμ, μμ κ°μ΄
django-extensions
ν¨ν€μ§λ₯Ό μ¬μ©ν λ μμ£Ό λ°μν©λλ€. κ±°μ 2λ λμ 건λλ¦° μ μ΄ μλλ° μ°κ²°λ MRμ λ³ν©νλ λ° λ¬Έμ κ° μμ΅λκΉ?