forked from PyAr/CDPedia
/
cdpedia.py
executable file
·212 lines (174 loc) · 6.9 KB
/
cdpedia.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
#!/usr/bin/env python
# -*- coding: utf8 -*-
# Copyright 2006-2012 CDPedistas (see AUTHORS.txt)
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranties of
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# For further info, check http://code.google.com/p/cdpedia/
import os
import sys
import codecs
import platform
import optparse
import threading
import traceback
import webbrowser
# change execution path, so we can access all cdpedia internals (code and
# libraries)
cdpedia_path = os.path.abspath(__file__)
os.chdir(os.path.dirname(cdpedia_path))
# fix path if needed
if os.path.exists("cdpedia"):
sys.path.append("cdpedia")
# Logeamos stdout y stderr si estamos en windows, salvo que sea un debug build
# para construir el exe
if platform.system() == 'Windows' and not os.path.exists('debug'):
log_filename = os.path.join(os.path.expanduser('~'), 'cdpedia.log')
try:
log = codecs.open(log_filename, 'w', 'utf8', errors='replace')
sys.stdout = log
sys.stderr = log
except: # Si no podemos logear ni mostrar el error porque no
pass # tenemos una consola no podemos hacer nada.
from src import third_party # Need this to import thirdparty (werkzeug and jinja2)
from werkzeug.serving import ThreadedWSGIServer
from src.utiles import WatchDog, find_open_port
from src.web.web_app import create_app
import config
# imports extras para pyinstaller
import SocketServer
import Queue
import uuid
def handle_crash(type, value, tb):
'''Function to handle any exception that is not addressed explicitly.'''
if issubclass(type, KeyboardInterrupt):
# Nos vamos!
print "Saliendo por pedido del usuario"
cd_wd_timer.cancel()
sys.exit(0)
else:
exception = traceback.format_exception(type, value, tb)
exception = "".join(exception)
print exception
def close():
''' Cierra el servidor y termina cdpedia '''
print "Saliendo por watchdog timer"
server.shutdown()
sys.exit(0)
def cd_watch_dog():
''' Comprueba que el CD está puesto '''
global cd_wd_timer
try:
archivos = os.listdir('.')
except OSError:
# El CD no esta disponible
close()
if not 'cdpedia.py' in archivos:
# El CD no es CDPedia
close()
# Sigue andando, probemos mas tarde
cd_wd_timer = threading.Timer(CD_WD_SECONDS, cd_watch_dog)
cd_wd_timer.daemon = True
cd_wd_timer.start()
def sleep_and_browse():
server_up.wait()
if config.EDICION_ESPECIAL is None:
index = "http://%s:%d/" % (config.HOSTNAME, config.PORT)
else:
index = "http://%s:%d/%s/%s" % (config.HOSTNAME, config.PORT,
config.EDICION_ESPECIAL, config.INDEX)
webbrowser.open(index)
# En Python 2.5 el SocketServer no tiene un shutdown, así que si estamos
# en esa versión, lo ponemos nosotros (copiado de 2.6, basicamente).
if sys.version_info < (2, 6):
import select
import socket
ThreadedWSGIServer._is_shut_down = threading.Event()
ThreadedWSGIServer._shutdown_request = False
def serve_forever(self):
"""Handle one request at a time until shutdown."""
self._is_shut_down.clear()
try:
while not self._shutdown_request:
r, w, e = select.select([self], [], [], .5)
if self not in r:
continue
try:
request, client_address = self.get_request()
except socket.error:
continue
if not self.verify_request(request, client_address):
continue
try:
self.process_request(request, client_address)
except:
self.handle_error(request, client_address)
self.close_request(request)
finally:
self._shutdown_request = False
self._is_shut_down.set()
ThreadedWSGIServer.serve_forever = serve_forever
def shutdown(self):
"""Stops the serve_forever loop."""
self._shutdown_request = True
self._is_shut_down.wait()
ThreadedWSGIServer.shutdown = shutdown
if __name__ == "__main__":
parser = optparse.OptionParser()
parser.add_option("-v", "--verbose", action="store_true", default=False,
dest="verbose", help="muestra info de lo que va haciendo")
parser.add_option("-d", "--daemon", action="store_true", default=False,
dest="daemon", help="daemonize server")
parser.add_option("-p", "--port", type="int", dest="port",
default=config.PORT)
parser.add_option("-m", "--host", type="str", dest="hostname",
default=config.HOSTNAME)
(options, args) = parser.parse_args()
sys.excepthook = handle_crash
if options.daemon:
port = options.port
else:
port = find_open_port(starting_from=options.port, host=options.hostname)
config.PORT, config.HOSTNAME = port, options.hostname
if not options.daemon:
server_up = threading.Event()
# CD WatchDog timer
cd_wd_timer = None
# Tiempo entre llamadas a cd_watch_dog en segundos
CD_WD_SECONDS = 10
cd_wd_timer = threading.Timer(CD_WD_SECONDS, cd_watch_dog)
cd_wd_timer.daemon = True
cd_wd_timer.start()
threading.Thread(target=sleep_and_browse).start()
browser_watchdog = None
if config.BROWSER_WD_SECONDS:
browser_watchdog = WatchDog(callback=close, sleep=config.BROWSER_WD_SECONDS)
# Iniciamos el watchdog por más que aún no esté levantado el browser ya que
# el tiempo del watchdog es mucho mayor que el que se tarda en levantar el server
# y el browser.
browser_watchdog.start()
if options.verbose:
print "Levantando el server..."
app = create_app(browser_watchdog, verbose=options.verbose)
server = ThreadedWSGIServer(config.HOSTNAME, config.PORT, app, handler=None,
passthrough_errors=False)
server_up.set()
server.serve_forever()
if options.verbose:
print "Terminado, saliendo."
cd_wd_timer.cancel()
else:
app = create_app(watchdog=None, verbose=options.verbose)
server = ThreadedWSGIServer(config.HOSTNAME, port, app, handler=None,
passthrough_errors=False)
server.serve_forever()