changeset 54:496714f2fd8c

first live version of pics2
author paulo
date Mon, 03 Jun 2013 00:30:24 -0700
parents 0482bffd7d7f
children 0fbe37b56e84
files pics2/pics_app.py
diffstat 1 files changed, 170 insertions(+), 102 deletions(-) [+]
line diff
     1.1 --- a/pics2/pics_app.py	Sat Jun 01 20:43:00 2013 -0700
     1.2 +++ b/pics2/pics_app.py	Mon Jun 03 00:30:24 2013 -0700
     1.3 @@ -2,6 +2,9 @@
     1.4  import re
     1.5  import glob
     1.6  import traceback
     1.7 +import datetime
     1.8 +import random
     1.9 +import urlparse
    1.10  
    1.11  import html
    1.12  
    1.13 @@ -14,14 +17,19 @@
    1.14  
    1.15  
    1.16  
    1.17 -def _get_pics_url(environ, dirpath):
    1.18 -	script_name = environ.get("SCRIPT_NAME", '')
    1.19 -	return os.path.normpath(os.path.join(os.path.dirname(script_name), dirpath))
    1.20 +def _is_pics_dir(dirpath):
    1.21 +	return os.path.exists(os.path.join(dirpath, "_picsroot"))
    1.22  
    1.23  
    1.24 -def _get_app_url(environ, dirpath):
    1.25 -	script_name = environ.get("SCRIPT_NAME", '')
    1.26 -	return os.path.normpath(os.path.join(script_name, dirpath))
    1.27 +def _get_dir_dt(dirpath):
    1.28 +	if _is_pics_dir(dirpath):
    1.29 +		dirpath = os.path.join(dirpath, "_picsroot")
    1.30 +
    1.31 +	return datetime.datetime.fromtimestamp(os.stat(dirpath).st_mtime)
    1.32 +
    1.33 +
    1.34 +def _format_dt(dt):
    1.35 +	return dt.strftime("%Y-%m-%d")
    1.36  
    1.37  
    1.38  def _parse_path_info(path_info):
    1.39 @@ -32,18 +40,6 @@
    1.40  	return ppi
    1.41  
    1.42  
    1.43 -def _get_standard_html_doc(title):
    1.44 -	root = html.HTML("html")
    1.45 -
    1.46 -	header = root.header
    1.47 -	header.title(title)
    1.48 -
    1.49 -	body = root.body
    1.50 -	body.h1(title)
    1.51 -
    1.52 -	return (root, header, body)
    1.53 -
    1.54 -
    1.55  def _numeric_pad_basename(path, maxdigits=20):
    1.56  	return os.path.basename(path).zfill(maxdigits)
    1.57  
    1.58 @@ -57,98 +53,170 @@
    1.59  	logging.debug("browse_fns = %s" % browse_fns)
    1.60  
    1.61  	return zip(thumb_fns, browse_fns)
    1.62 -
    1.63 -
    1.64 -def _go_thumbnail_links_to_browse_imgs_html_body(environ, body, t, b):
    1.65 -	thumb_img_url = _get_pics_url(environ, t)
    1.66 -	browse_url = _get_app_url(environ, b)
    1.67 -	body.a(href=browse_url).img(src=thumb_img_url)
    1.68 -
    1.69 -
    1.70 -def main(environ):
    1.71 -	page_func = None
    1.72 -
    1.73 -	logging.debug("environ['PATH_INFO'] = %s" % environ["PATH_INFO"])
    1.74 -	logging.debug("environ['SCRIPT_NAME'] = %s" % environ["SCRIPT_NAME"])
    1.75 -
    1.76 -	pi = environ["PATH_INFO"]
    1.77 -	ppi = _parse_path_info(pi)
    1.78 -	logging.debug("ppi = %s" % ppi)
    1.79 -
    1.80 -	if len(ppi) < 1 or ppi[0] != '':
    1.81 -		raise AssertionError("Parsed path length must start empty: " + pi)
    1.82 -
    1.83 -	if len(ppi) >= 2 and os.path.exists(os.path.join(ppi[1], "_picsroot")):
    1.84 -		if len(ppi) == 2:
    1.85 -			page_func = page_thumbs
    1.86 -		elif len(ppi) >= 4 and ppi[2] == "browse" and os.path.exists(os.path.join(*ppi)):
    1.87 -			page_func = page_browse
    1.88 -	elif len(ppi) == 1:
    1.89 -		page_func = page_index
    1.90 -
    1.91 -	if page_func is None:
    1.92 -		raise RuntimeError("Cannot find path: " + pi)
    1.93 -	
    1.94 -	return unicode(page_func(environ)).encode("utf-8")
    1.95  	
    1.96  
    1.97 -def page_index(environ):
    1.98 -	(html_root, html_header, html_body) = _get_standard_html_doc("pics index")
    1.99 +class Main:
   1.100 +	def _get_pics_url(self, dirpath):
   1.101 +		script_name = self._environ.get("SCRIPT_NAME", '')
   1.102 +		return os.path.normpath(os.path.join(os.path.dirname(script_name), dirpath))
   1.103 +	
   1.104 +	
   1.105 +	def _get_app_url(self, dirpath):
   1.106 +		script_name = self._environ.get("SCRIPT_NAME", '')
   1.107 +		return os.path.normpath(os.path.join(script_name, dirpath))
   1.108 +	
   1.109 +	
   1.110 +	def _get_standard_html_doc(self, title):
   1.111 +		root = html.HTML("html")
   1.112 +	
   1.113 +		header = root.header
   1.114 +		header.link(rel="stylesheet", type="text/css", href=self._get_pics_url("index.css"))
   1.115 +		header.title(title)
   1.116 +	
   1.117 +		body = root.body
   1.118 +		body.h1(title)
   1.119 +	
   1.120 +		return (root, header, body)
   1.121 +	
   1.122 +	
   1.123 +	def _go_thumbnail_links_to_browse_imgs_html_body(self, body, t, b, selclass=None):
   1.124 +		thumb_img_url = self._get_pics_url(t)
   1.125 +		browse_url = self._get_app_url(b)
   1.126  
   1.127 -	return html_root
   1.128 +		a = body.a(href=browse_url)
   1.129  
   1.130 +		if selclass is not None:
   1.131 +			a.img(src=thumb_img_url, klass=selclass)
   1.132 +		else:
   1.133 +			a.img(src=thumb_img_url)
   1.134  
   1.135 -def page_thumbs(environ):
   1.136 -	ppi = _parse_path_info(environ["PATH_INFO"])
   1.137 -	d = os.path.join(*ppi)
   1.138 -	(html_root, html_header, html_body) = _get_standard_html_doc(d)
   1.139 +		body.text(' ')
   1.140 +	
   1.141 +	
   1.142 +	def __init__(self, environ):
   1.143 +		self._environ = environ
   1.144 +		self._page_func = None
   1.145 +	
   1.146 +		#logging.debug("environ = %s" % (sorted(self._environ.items(), key=lambda x: x[0]),))
   1.147 +		logging.debug("environ['PATH_INFO'] = %s" % self._environ["PATH_INFO"])
   1.148 +		logging.debug("environ['SCRIPT_NAME'] = %s" % self._environ["SCRIPT_NAME"])
   1.149 +		logging.debug("environ['QUERY_STRING'] = %s" % self._environ["QUERY_STRING"])
   1.150 +	
   1.151 +		pi = self._environ["PATH_INFO"]
   1.152 +		ppi = _parse_path_info(pi)
   1.153 +		logging.debug("ppi = %s" % ppi)
   1.154 +	
   1.155 +		if len(ppi) < 1 or ppi[0] != '':
   1.156 +			raise AssertionError("Parsed path length must start empty: " + pi)
   1.157 +	
   1.158 +		if len(ppi) >= 2 and _is_pics_dir(ppi[1]):
   1.159 +			if len(ppi) == 2:
   1.160 +				self._page_func = self.page_thumbs
   1.161 +			elif len(ppi) >= 4 and ppi[2] == "browse" and os.path.exists(os.path.join(*ppi)):
   1.162 +				self._page_func = self.page_browse
   1.163 +		elif len(ppi) == 1:
   1.164 +			self._page_func = self.page_index
   1.165 +	
   1.166 +		if self._page_func is None:
   1.167 +			raise RuntimeError("Cannot find path: " + pi)
   1.168 +		
   1.169  
   1.170 -	html_p = html_body.p
   1.171 -	for (t, b) in _get_images(d):
   1.172 -		_go_thumbnail_links_to_browse_imgs_html_body(environ, html_p, t, b)
   1.173 +	def page(self):
   1.174 +		return unicode(self._page_func()).encode("utf-8")
   1.175 +	
   1.176  
   1.177 -	return html_root
   1.178 +	def page_index(self):
   1.179 +		n = 5 # number of thumbnails to display
   1.180  
   1.181 +		(html_root, html_header, html_body) = self._get_standard_html_doc("Pictures")
   1.182 +	
   1.183 +		pics_dirs = []
   1.184 +		for i in os.listdir('.'):
   1.185 +			if _is_pics_dir(i):
   1.186 +				pics_dirs.append((i, _get_dir_dt(i)))
   1.187 +	
   1.188 +		pics_dirs.sort(key=lambda x: x[1], reverse=True)
   1.189 +	
   1.190 +		for (d, dt) in pics_dirs:
   1.191 +			html_body.h2.a(d, href=self._get_app_url(d))
   1.192 +			html_body.h3(_format_dt(dt))
   1.193 +	
   1.194 +			imgs = _get_images(d)
   1.195 +			imgs_idx = [(i, img) for (i, img) in enumerate(imgs)]
   1.196 +			
   1.197 +			sampled_imgs_idx = random.sample(imgs_idx, min(len(imgs_idx), n))
   1.198 +			sampled_imgs_idx.sort(key=lambda x: x[0])
   1.199 +			
   1.200 +			html_p = html_body.p
   1.201 +			for (i, (t, b)) in sampled_imgs_idx:
   1.202 +				self._go_thumbnail_links_to_browse_imgs_html_body(html_p, t, b)
   1.203 +			
   1.204 +		return html_root
   1.205 +	
   1.206 +	
   1.207 +	def page_thumbs(self):
   1.208 +		ppi = _parse_path_info(self._environ["PATH_INFO"])
   1.209 +		d = os.path.join(*ppi)
   1.210 +		(html_root, html_header, html_body) = self._get_standard_html_doc(d)
   1.211  
   1.212 -def page_browse(environ):
   1.213 -	ppi = _parse_path_info(environ["PATH_INFO"])
   1.214 -	d = os.path.join(*ppi[:2])
   1.215 -	imgs = _get_images(d)
   1.216 -	img = os.path.join(*ppi)
   1.217 -
   1.218 -	# thumbnail preview ribbon
   1.219 -	w = 7 # must be odd
   1.220 -	v = w/2
   1.221 -	imgs_circ = [None] * w
   1.222 -	x = None
   1.223 -	n = len(imgs)
   1.224 -	for (i, (t, b)) in enumerate(imgs):
   1.225 -		if b == img:
   1.226 -			x = i + 1
   1.227 -			imgs_circ[v] = (t, b)
   1.228 -			for j in range(1, v + 1):
   1.229 -				if (i + j) < n: imgs_circ[v + j] = imgs[i + j]
   1.230 -				if (i - j) >= 0: imgs_circ[v - j] = imgs[i - j]
   1.231 -					
   1.232 -			break
   1.233 -
   1.234 -	if x is None:
   1.235 -		raise AssertionError
   1.236 -
   1.237 -	(html_root, html_header, html_body) = _get_standard_html_doc(u"%s \u2014 %s of %s" % (d, x, len(imgs)))
   1.238 -
   1.239 -	browse_img_url = _get_pics_url(environ, img)
   1.240 -	html_body.p.img(src=browse_img_url)
   1.241 -
   1.242 -	logging.debug("imgs_circ = %s" % imgs_circ)
   1.243 -
   1.244 -	html_p_ribbon = html_body.p
   1.245 -	for i in imgs_circ:
   1.246 -		if i is not None:
   1.247 -			(t, b) = i
   1.248 -			_go_thumbnail_links_to_browse_imgs_html_body(environ, html_p_ribbon, t, b)
   1.249 -
   1.250 -	return html_root
   1.251 +		qs = urlparse.parse_qs(self._environ["QUERY_STRING"])
   1.252 +		from_img = None
   1.253 +		if "from" in qs:
   1.254 +			from_img = qs["from"][0]
   1.255 +	
   1.256 +		html_p = html_body.p
   1.257 +		for (t, b) in _get_images(d):
   1.258 +			if from_img is not None and b == from_img:
   1.259 +				self._go_thumbnail_links_to_browse_imgs_html_body(html_p, t, b, "sel2")
   1.260 +			else:
   1.261 +				self._go_thumbnail_links_to_browse_imgs_html_body(html_p, t, b)
   1.262 +	
   1.263 +		html_body.a("(Other pictures)", href=self._get_app_url(''))
   1.264 +		return html_root
   1.265 +	
   1.266 +	
   1.267 +	def page_browse(self):
   1.268 +		ppi = _parse_path_info(self._environ["PATH_INFO"])
   1.269 +		d = os.path.join(*ppi[:2])
   1.270 +		imgs = _get_images(d)
   1.271 +		img = os.path.join(*ppi)
   1.272 +	
   1.273 +		# thumbnail preview ribbon
   1.274 +		w = 7 # must be odd
   1.275 +		v = w/2
   1.276 +		imgs_circ = [None] * w
   1.277 +		x = None
   1.278 +		n = len(imgs)
   1.279 +		for (i, (t, b)) in enumerate(imgs):
   1.280 +			if b == img:
   1.281 +				x = i + 1
   1.282 +				imgs_circ[v] = (t, b)
   1.283 +				for j in range(1, v + 1):
   1.284 +					if (i + j) < n: imgs_circ[v + j] = imgs[i + j]
   1.285 +					if (i - j) >= 0: imgs_circ[v - j] = imgs[i - j]
   1.286 +						
   1.287 +				break
   1.288 +	
   1.289 +		if x is None:
   1.290 +			raise AssertionError
   1.291 +	
   1.292 +		(html_root, html_header, html_body) = self._get_standard_html_doc(u"%s \u2014 %s of %s" % (d, x, len(imgs)))
   1.293 +	
   1.294 +		browse_img_url = self._get_pics_url(img)
   1.295 +		html_body.p.img(src=browse_img_url)
   1.296 +	
   1.297 +		logging.debug("imgs_circ = %s" % imgs_circ)
   1.298 +	
   1.299 +		html_p = html_body.p
   1.300 +		for i in imgs_circ:
   1.301 +			if i is not None:
   1.302 +				(t, b) = i
   1.303 +				if b == img:
   1.304 +					self._go_thumbnail_links_to_browse_imgs_html_body(html_p, t, d + "?from=" + img, "sel")
   1.305 +				else:
   1.306 +					self._go_thumbnail_links_to_browse_imgs_html_body(html_p, t, b)
   1.307 +	
   1.308 +		return html_root
   1.309  
   1.310  
   1.311  def app(environ, start_response):
   1.312 @@ -156,7 +224,7 @@
   1.313  	response_type = "text/plain; charset=UTF-8"
   1.314  
   1.315  	try:
   1.316 -		response_body = main(environ)
   1.317 +		response_body = Main(environ).page()
   1.318  		response_code = "200 OK"
   1.319  		response_type = "text/html; charset=UTF-8"
   1.320  	except: