Skip to content
This repository has been archived by the owner on Nov 23, 2020. It is now read-only.

Commit

Permalink
use file_response function in MediaMixin.serve_file method. FileRoute…
Browse files Browse the repository at this point in the history
…r is now a proxy for MediaRouter #release-note=wsgi
  • Loading branch information
lsbardel committed Feb 19, 2016
1 parent df1be4b commit c012af1
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 83 deletions.
1 change: 1 addition & 0 deletions README.rst
Expand Up @@ -75,6 +75,7 @@ Out of the box it is shipped with the the following:

* Socket servers
* WSGI server
* HTTP client
* JSON-RPC_
* Web Sockets
* Test suite
Expand Down
17 changes: 15 additions & 2 deletions agile.json
Expand Up @@ -2,13 +2,26 @@
"github": {
"pulsar": {
"python_module": "pulsar",
"version": "pulsar.__version__"
"version": "pulsar.__version__",
"release-notes": "docs/source/history",
"dist": {
"shell": [
"rm -rf dist",
"{{ python }} setup.py sdist upload"
],
"files": "dist/*.gz"
}
}
},
"shell": {
"pulsar": {
"command": ["rm -rf dist",
"{{ python }} setup.py sdist"]
},
"tasks": {
"release": {
"description": "make a new release to github",
"command": ["github"]
"command": ["github:pulsar"]
}
}
}
40 changes: 25 additions & 15 deletions docs/source/history/1.1.md
@@ -1,5 +1,20 @@
Ver. 1.1.2 - 2016-Feb-04
============================
## Ver. 1.1.3 - 2016-Feb-18

* fixes [#198](https://github.com/quantmind/pulsar/issues/198)
* make sure the ``asyncio.coroutine`` decorator is used by all pulsar coroutines. this allows to use pulsar to write python 3.5 compatible code with the ``async/await`` syntax [709f9ff](https://github.com/quantmind/pulsar/commit/709f9ff0e9df9858100a9b2e2ef154ad57391a07)
* Fixes [#159](https://github.com/quantmind/pulsar/issues/159)

### Documentation
* Removed changelog.rst from the top level directory and created a folder inside the docs which contains a list of minor releases. started using markdown in documentation too. [6b20825](https://github.com/quantmind/pulsar/commit/6b208259b5937fd0e4468dcb263e2f365df86a66)

### Http
* Better keep-alive management of http connections [df1be4b](https://github.com/quantmind/pulsar/commit/df1be4bc4347b7d71de677bc73d5b8c9085d90f7)
* Http client use the base class connection method rather than using a diferent one [b584828](https://github.com/quantmind/pulsar/commit/b5848289bb0605ebe97d1179260b47d9889a9887)
* The http response object has the links attribute which return a parsed links headers dictionary. code from python requests. [023ca50](https://github.com/quantmind/pulsar/commit/023ca508d2ecd222924e0e1087ea88a6cbbaadda)


## Ver. 1.1.2 - 2016-Feb-04

* Removed ``release`` application and created a [new repository](https://github.com/quantmind/pulsar-agile) for it
* ``wait`` method in ``greenio`` app accepts an extra parameter for checking if in child greenlet
* Specialised ``MustBeInChildGreenlet`` error for functions which should be called on a child greenlet
Expand All @@ -9,21 +24,19 @@ Ver. 1.1.2 - 2016-Feb-04
* Introduced ``pulsar.ensure_future`` in place of ``pulsar.async``


Ver. 1.1.1 - 2016-Jan-06
============================
## Ver. 1.1.1 - 2016-Jan-06

* Full support for python 3.5
* Pulsar **1.1.x** is the last minor release ("major.minor.micro") to support python 3.4
* From pulsar **1.2.x**, support for python 3.4 will be dropped and the new
[async-await][] syntax will be used in the whole codebase

Core
-----------------
### Core
* Added CI for python 3.5
* Added ``debug`` properties to all ``AsyncObject``. The property returns the event loop
debug mode flag

HttpClient
----------------
### Http
* Backward incompatible changes with API much closer to [requests][] and far better support for streaming both uploads and downloads
* Added ``content`` attribute to ``HttpResponse``, in line with [requests][]
* Ability to pass ``stream=True`` during a request, same API as python [requests][]
Expand All @@ -36,22 +49,19 @@ HttpClient
* Tidy up ``CONNECT`` request url (for tunneling)
* Added tests for proxyserver example using [requests][]

WSGI
------
### Wsgi
* Both ``wsgi`` and ``http`` apps use the same ``pulsar.utils.httpurl.http_chunks``
function for transfer-encoding ``chunked``
* ``render_error`` escapes the Exception message to prevent [XSS][]

Data Store
-----------
### Datastore
* Better ``pulsards_url`` function, default value form ``cfg.data_store``
* ``key_value_save`` set to empty list by default (no persistence)

Examples
-------------
### Examples
* Refactored proxy server example
* Updated django chat example so that warning are no longer issued

[requests]: http://docs.python-requests.org/
[XSS]: https://en.wikipedia.org/wiki/Cross-site_scripting
[async-await]: https://www.python.org/dev/peps/pep-0492/#specification
[async-await]: https://www.python.org/dev/peps/pep-0492/#specification
56 changes: 4 additions & 52 deletions pulsar/apps/wsgi/routers.py
Expand Up @@ -552,27 +552,7 @@ def was_modified_since(cls, header=None, mtime=0, size=0):
return True

def serve_file(self, request, fullpath, status_code=None):
# Respect the If-Modified-Since header.
statobj = os.stat(fullpath)
content_type, encoding = mimetypes.guess_type(fullpath)
response = request.response
if content_type:
response.content_type = content_type
if encoding:
response.encoding = encoding
if not (status_code or self.was_modified_since(
request.environ.get('HTTP_IF_MODIFIED_SINCE'),
statobj[stat.ST_MTIME],
statobj[stat.ST_SIZE])):
response.status_code = 304
else:
response.content = open(fullpath, 'rb').read()
if status_code:
response.status_code = status_code
else:
response.headers["Last-Modified"] = http_date(
statobj[stat.ST_MTIME])
return response
return file_response(request, fullpath, status_code=status_code)

def directory_index(self, request, fullpath):
names = [Html('a', '../', href='../', cn='folder')]
Expand Down Expand Up @@ -621,13 +601,12 @@ class MediaRouter(Router, MediaMixin):

def __init__(self, rule, path, show_indexes=False,
default_suffix=None, default_file='index.html',
raise_404=True, **params):
**params):
super().__init__('%s/<path:path>' % rule, **params)
self._default_suffix = default_suffix
self._default_file = default_file
self._show_indexes = show_indexes
self._file_path = path
self._raise_404 = raise_404

def filesystem_path(self, request):
path = request.urlargs['path']
Expand All @@ -653,37 +632,10 @@ def get(self, request):
if '.' not in filename and self._default_suffix:
fullpath = '%s.%s' % (fullpath, self._default_suffix)
#
if os.path.isfile(fullpath):
return self.serve_file(request, fullpath)
elif self._raise_404:
raise Http404
return self.serve_file(request, fullpath)


class FileRouter(Router, MediaMixin):
'''A Router for a single file
'''
response_content_types = RouterParam(('application/octet-stream',
'text/css',
'application/javascript',
'text/html'))
cache_control = CacheControl(maxage=86400)

def __init__(self, route, file_path, status_code=None, raise_404=True):
super().__init__(route)
self._status_code = status_code
self._file_path = file_path
self._raise_404 = raise_404

def filesystem_path(self, request):
return self._file_path

def get(self, request):
fullpath = self.filesystem_path(request)
if os.path.isfile(fullpath):
return self.serve_file(request, fullpath,
status_code=self._status_code)
elif self._raise_404:
raise Http404
FileRouter = MediaRouter


def file_response(request, filepath, block=None, status_code=None,
Expand Down
6 changes: 5 additions & 1 deletion pulsar/async/clients.py
Expand Up @@ -156,7 +156,11 @@ def _put(self, conn, discard=False):
self._in_use_connections.discard(conn)

def is_connection_closed(self, connection):
if is_socket_closed(connection.sock):
try:
sock = connection.sock
except AttributeError:
return True
if is_socket_closed(sock):
connection.close()
return True
return False
Expand Down
13 changes: 0 additions & 13 deletions pulsar/async/futures.py
Expand Up @@ -12,7 +12,6 @@
__all__ = ['maybe_async',
'run_in_loop',
'add_errback',
'add_callback',
'task_callback',
'multi_async',
'as_coroutine',
Expand Down Expand Up @@ -94,18 +93,6 @@ def _error_back(fut):
return future


def add_callback(future, callback, loop=None):
'''Add a ``callback`` to ``future`` executed only if an exception
has not occurred.'''
def _call_back(fut):
if not (fut._exception or fut.cancelled()):
callback(fut.result())

future = ensure_future(future, loop=None)
future.add_done_callback(_call_back)
return future


def future_result_exc(future):
'''Return a two elements tuple containing the future result and exception.
Expand Down

0 comments on commit c012af1

Please sign in to comment.