summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbin/3Drotate (renamed from 3Drotate)0
-rwxr-xr-xbin/bevelborder (renamed from bevelborder)0
-rwxr-xr-xbin/grid (renamed from grid)0
-rwxr-xr-xbreaker.py151
-rwxr-xr-xgradient.py103
-rwxr-xr-ximgrid.py198
-rw-r--r--install/pb_nginx.conf (renamed from pb_nginx.conf)0
-rw-r--r--lib/__init__.py (renamed from README.md)0
-rwxr-xr-xlib/db.py (renamed from db.py)0
-rw-r--r--lib/utils.py122
-rwxr-xr-xpattern.py151
-rwxr-xr-xpbserver.py19
-rw-r--r--s3.py618
-rw-r--r--s3config.py3
14 files changed, 261 insertions, 1104 deletions
diff --git a/3Drotate b/bin/3Drotate
index 227b92d..227b92d 100755
--- a/3Drotate
+++ b/bin/3Drotate
diff --git a/bevelborder b/bin/bevelborder
index 6f6ec2a..6f6ec2a 100755
--- a/bevelborder
+++ b/bin/bevelborder
diff --git a/grid b/bin/grid
index 58d0e08..58d0e08 100755
--- a/grid
+++ b/bin/grid
diff --git a/breaker.py b/breaker.py
index 4bb5bf9..06c89cf 100755
--- a/breaker.py
+++ b/breaker.py
@@ -1,29 +1,18 @@
#!/usr/bin/python2.7
-from subprocess import call, Popen, PIPE
-import urllib
-import urllib2
import os
import sys
import random
import re
-import time
-urlencode = urllib.urlencode
-urlopen = urllib2.urlopen
-Request = urllib2.Request
+import lib.utils as utils
+import urllib
+from config import *
-#WORKING_DIR = "/tmp"
-WORKING_DIR = "/var/www/cache"
-BIN_CONVERT = "/usr/bin/convert"
-BIN_IDENTIFY = "/usr/bin/identify"
DEFAULT_FINALFORMAT = "png";
-
SUBTLE_BREAK_MARK = 'pron'
EXTREME_BREAK_MARK = 'sugar'
HEADER_OFFSET = 2000
-MAX_SIZE = 1024 * 1024 * 1.2 * 1.5
-
# 'CLASSIC':'jpg',
# 'REDUX':'pcds',
# 'BLURRY_BREAK':'viff',
@@ -37,99 +26,10 @@ MAX_SIZE = 1024 * 1024 * 1.2 * 1.5
# 'FAX_MACHINE':'cals',
# 'STRIPES':'exr',
# 'PHOTOCOPY':'art',
-TEST_PARAMS = {
- "url" : "http://i.asdf.us/im/27/1424816234661dumpfmpfifferkinggr_1424816412_pfifferking.gif" ,
- "breaktype" : "RGB_WASH",
- "finalformat" : "png",
- "breakmode" : "extreme",
- "breakangle" : "10",
- "username" : "donkey",
- "expanded" : "false"
-}
-
-def bool_correct(s):
- if re.match(r'^false$', s, re.IGNORECASE):
- return False
- elif re.match(r'^true$', s, re.IGNORECASE):
- return True
- else:
- return s
-
-#{{{Utility functions
-class dotdict(dict):
- """dot.notation access to dictionary attributes"""
- def __getattr__(self, attr):
- return self.get(attr)
- __setattr__= dict.__setitem__
- __delattr__= dict.__delitem__
-def sanitize (str):
- return re.sub(r'\W+', '', str)
-
-def now():
- return int(time.time())
-
-def browser_request (url, data=None):
- headers = {
- 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
- 'Accept': '*/*',
- }
- try:
- req = Request(url, data, headers)
- response = urlopen(req)
- except IOError, e:
- if hasattr(e, 'code'):
- sys.stderr.write( '%s - ERROR %s' % (url, e.code) )
- raise;
- return None
- else:
- return response
-
-def download(url, destination, max_size=MAX_SIZE):
- response = browser_request(url, None)
- rawimg = response.read()
- if len(rawimg) == 0:
- sys.stderr.write("got zero-length file")
- raise;
- if len(rawimg) > max_size:
- sys.stderr.write("file too big: max size {} KB / {} is {} KB".format(
- str(MAX_SIZE/1024),
- destination,
- str(len(rawimg)/1024)
- ))
- raise;
- f = open(destination, "w")
- f.write(rawimg)
- f.close()
-
-def dimensions (filepath):
- #works in lieu of a mimetype check (it reads the header as well)
- ident = (Popen([BIN_IDENTIFY, filepath], stdout=PIPE).communicate()[0]).split(" ")
- return ident[2].split("x")
-
-def file_size (filepath):
- try:
- return os.stat(file)[6]
- except Exception as e:
- sys.stderr.write(str(e))
- raise;
-
-def gif_frames(filepath):
- try:
- info = Popen([BIN_IDENTIFY,filepath], stdout=PIPE).communicate()[0]
- frames = filter((lambda x: x), map(
- (lambda x: x.split(" ")[0]),
- (info).split('\n')
- ))
- return frames
- except Exception as e:
- sys.stderr.write(str(e))
- raise;
-#}}}
class Breaker():
- def __init__(self, params):
+ def __init__(self, **kwargs):
self.params = {}
- self.now = now()
self.tag = "imBreak"
self.commands = [];
self._required_keys = [
@@ -143,31 +43,31 @@ class Breaker():
]
self.files_created = []
for k in self._required_keys:
- if k in params:
+ if k in kwargs:
if k == 'breaktype':
- self.params['breaktype'] = self._get_breaktype(params[k])
+ self.params['breaktype'] = self._get_breaktype(kwargs[k])
elif k == 'url':
- self.params[k] = params[k]
+ self.params[k] = kwargs[k]
else:
- self.params[k] = bool_correct(sanitize(params[k]))
+ self.params[k] = utils.bool_correct(utils.sanitize(kwargs[k]))
else:
self.params[k] = False;
- self.params = dotdict(self.params)
+ self.params = utils.dotdict(self.params)
self.basename, self._first_format = self._get_filename();
self._downloaded_file = os.path.join(WORKING_DIR, "IMBREAKTMP{}.{}".format(self.basename, self._first_format)) # same here
try:
- download(self.params.url, self._downloaded_file)
+ utils.download(self.params.url, self._downloaded_file)
self.files_created.append(self._downloaded_file)
except Exception as e:
sys.stderr.write(str(e))
raise;
- self._gif_frames = gif_frames(self._downloaded_file)
+ self._gif_frames = utils.gif_frames(self._downloaded_file)
self._gif_frames = self._gif_frames if len(self._gif_frames) > 1 else False
- self.width, self.height = dimensions(self._downloaded_file) # same here
+ self.width, self.height = utils.dimensions(self._downloaded_file) # same here
if not self.params.finalformat:
self.params.finalformat = DEFAULT_FINALFORMAT
@@ -179,19 +79,15 @@ class Breaker():
#final filepath is stored in self.filepath
self.filename = "{}.{}".format(self.basename, self.params.finalformat)
self.filepath = os.path.join(WORKING_DIR, self.filename)
- #lets go back to this in a second
self._conversion_file = os.path.join(WORKING_DIR, "IMBREAKTMP{}.{}".format(self.basename, self.params.breaktype)) # this
def _call_cmd(self, cmd, error=""):
try:
- call(cmd)
+ utils.call_cmd(cmd)
self.commands.append(" ".join(cmd));
- except Exception as e:
- if error:
- sys.stderr.write(error)
- else:
- sys.stderr.write(str(e))
+ except Exception:
+ raise Exception("Unable to call cmd {}".format(str(cmd)))
def _get_breaktype(self, key):
#{{{ conversion table
@@ -224,8 +120,8 @@ class Breaker():
name_part = url.split("/")[-1]
try:
parts = name_part.split(".")
- name_part = sanitize(parts[-2])
- file_format = sanitize(parts[-1])
+ name_part = utils.sanitize(parts[-2])
+ file_format = utils.sanitize(parts[-1])
if not name_part or not file_format:
sys.stderr.write( "Incompatible input file type")
raise;
@@ -237,7 +133,7 @@ class Breaker():
raise;
if (len(name_part) > 20):
name_part = name_part[:-20]
- return "{}{}_{}_{}".format(self.tag, name_part, self.now, self.params.username or ""), file_format
+ return "{}{}_{}_{}".format(self.tag, name_part, utils.now(), self.params.username or ""), file_format
#{{{#########rotatefunctions#######################################
def _rotate(self):
@@ -357,6 +253,15 @@ class Breaker():
self._cleanup()
if __name__ == "__main__":
- b = Breaker(TEST_PARAMS)
+ TEST_PARAMS = {
+ "url" : "http://i.asdf.us/im/27/1424816234661dumpfmpfifferkinggr_1424816412_pfifferking.gif" ,
+ "breaktype" : "RGB_WASH",
+ "finalformat" : "png",
+ "breakmode" : "extreme",
+ "breakangle" : "10",
+ "username" : "donkey",
+ "expanded" : "false"
+ }
+ b = Breaker(**TEST_PARAMS)
b.create();
print b.filepath
diff --git a/gradient.py b/gradient.py
index 991f853..68de55b 100755
--- a/gradient.py
+++ b/gradient.py
@@ -5,26 +5,11 @@ from subprocess import call
import simplejson as json
import sys
import os
-import db
import sha
+import lib.utils as utils
+from config import *
-#{{{ logging
-#import logging
-#logger = logging.getLogger('gradient')
-#logging.FileHandler('/var/www/cache/gradient.log')
-#formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
-#hdlr.setFormatter(formatter)
-#logger.addHandler(hdlr)
-#logger.setLevel(logging.WARNING)
-#}}}
-def is_color(s):
- if s == "":
- return "transparent"
- if re.match('(rgba?\([0-9]+,[0-9]+,[0-9]+\))|([a-zA-Z]+)|(\#[A-Ha-h0-9]+)', s):
- return s.replace(' ','')
- else:
- raise ValueError
PARAM_LIST = [
"width", "height",
"color1", "color2",
@@ -40,20 +25,14 @@ PARAM_LIST = [
"gradienttype",
"username",
]
-BIN_CONVERT = "/usr/bin/convert"
-BIN_IDENTIFY = "/usr/bin/identify"
-BEVELBORDER = "./bevelborder"
DEFAULT_FORMAT = "png"
DEFAULT_COLORS = {
"color1" : "white",
"color2" : "black",
};
-#WORKING_DIR = '/tmp'
-WORKING_DIR = '/var/www/cache'
DEFAULT_WIDTH = "200"
DEFAULT_HEIGHT = "200"
-
DEFAULT_BEVEL_PERCENT = "12";
HALFTONEVALUES = {
@@ -65,36 +44,9 @@ HALFTONEVALUES = {
"flatstripes": "o2x2",
}
-TEST_FORM = {
- "width" : "200",
- "color1" : "#ffdead",
- "color2" : "blue",
- "stripes" : "true",
- "stripenumber" : "20",
- "gradienttype" : "radial",
- "stripeintensity" : "20",
- "halftone" : "checkeredfade",
- "percentbeveled" : "30",
- "flip" : "true",
- "bevel" : "flatinner",
- "rotate" : "20",
- "height" : "200",
- "filetype" : "jpg",
- "username" : "whatever"
-}
-
-def sanitize (s):
- return re.sub(re.compile(r'\W+'), '', s)
-
-def is_number(s):
- try:
- return int(s)
- except (ValueError, TypeError):
- return False
class Gradient:
- def __init__(self, form):
- self.now = int(time.time())
+ def __init__(self, **kwargs):
self.tag = "imGradient"
self.directory = WORKING_DIR
self.commands = []
@@ -103,20 +55,20 @@ class Gradient:
params = {}
for key in PARAM_LIST:
- if key in form:
+ if key in kwargs:
if key in ['color1', 'color2']:
- params[key] = is_color(form[key])
+ params[key] = utils.is_color(kwargs[key])
else:
- params[key] = sanitize(form[key])
+ params[key] = utils.sanitize(kwargs[key])
if key in ['rotate','tilt','blurriness','stripenumber','stripeintensity']:
- params[key] = params[key] if is_number(params[key]) else ""
+ params[key] = params[key] if utils.is_number(params[key]) else ""
elif key in ['brightness', 'contrast', 'hue']:
- if not is_number(params[key]) or params[key] == "100": params[key] = ""
+ if not utils.is_number(params[key]) or params[key] == "100": params[key] = ""
else:
params[key] = ""
- params['width'] = params['width'] if is_number(params['width']) else DEFAULT_WIDTH
- params['height'] = params['height'] if is_number(params['height']) else DEFAULT_HEIGHT
+ params['width'] = params['width'] if utils.is_number(params['width']) else DEFAULT_WIDTH
+ params['height'] = params['height'] if utils.is_number(params['height']) else DEFAULT_HEIGHT
params["color1"] = params["color1"] or DEFAULT_COLORS["color1"];
params["color2"] = params["color2"] or DEFAULT_COLORS["color2"];
self.params = params
@@ -125,25 +77,24 @@ class Gradient:
"flatout", "flatinner", "evenlyframed", "biginner",
"bigouter", "dramaticflatout", "dramaticflatinner",
]
+
def newfilename(self):
return "{}{}-{}_{}_{}.{}".format(
self.tag,
self.params['color1'].replace('#','').replace('(','-').replace(')','-'),
self.params['color2'].replace('#','').replace('(','-').replace(')','-'),
- self.now,
+ utils.now(),
self.params['username'],
self.params['filetype'] or DEFAULT_FORMAT,
)
- def _call_cmd(self, cmd, error=""):
+ def _call_cmd(self, cmd):
try:
- call(cmd)
+ utils.call_cmd(cmd)
self.commands.append(" ".join(cmd));
- except Exception as e:
- if error:
- sys.stderr.write(error)
- else:
- sys.stderr.write(str(e))
+ except Exception:
+ raise Exception("Unable to call cmd {}".format(str(cmd)))
+
def _build_cmd(self):
cmd = [BIN_CONVERT]
@@ -241,8 +192,24 @@ class Gradient:
self._make_bevel()
if __name__ == "__main__":
- g = Gradient(TEST_FORM);
+ TEST_FORM = {
+ "width" : "200",
+ "color1" : "#ffdead",
+ "color2" : "blue",
+ "stripes" : "true",
+ "stripenumber" : "20",
+ "gradienttype" : "radial",
+ "stripeintensity" : "20",
+ "halftone" : "checkeredfade",
+ "percentbeveled" : "30",
+ "flip" : "true",
+ "bevel" : "flatinner",
+ "rotate" : "20",
+ "height" : "200",
+ "filetype" : "jpg",
+ "username" : "whatever"
+ }
+ g = Gradient(**TEST_FORM);
g.create();
- print g.now
print " ".join(g.commands)
print g.filename
diff --git a/imgrid.py b/imgrid.py
index ece50b0..e294066 100755
--- a/imgrid.py
+++ b/imgrid.py
@@ -1,136 +1,20 @@
#!/usr/bin/python2.7
-
import sys
import re
import os
-import string
import simplejson as json
import random
-import time
-import urllib
-import urllib2
-from subprocess import Popen,PIPE,call
-urlencode = urllib.urlencode
-urlopen = urllib2.urlopen
-Request = urllib2.Request
-
-MAX_SIZE = 1024 * 1024 * 1.2 * 1.5
-WORKING_DIR = "/var/www/cache"
-#WORKING_DIR = "/tmp"
-
-BIN_CONVERT = "/usr/bin/convert"
-BIN_COMPOSITE = "/usr/bin/composite"
-BIN_IDENTIFY = "/usr/bin/identify"
-THREEDROTATE = "./3Drotate"
-GRID = "./grid"
-DB_TAG = "grid";
+import lib.utils as utils
+from config import *
+import tempfile
DEFAULT_HEIGHT = 400
DEFAULT_WIDTH = 600
DEFAULT_LINE_COLOR = "silver"
-DEFAULT_FINALFORMAT = "png"
-
-#{{{Utility functions
-def is_color(s):
- if s == "":
- return "transparent"
- if re.match('(rgba?\([0-9]+,[0-9]+,[0-9]+\))|([a-zA-Z]+)|(\#[A-Ha-h0-9]+)', s):
- return s.replace(' ', '');
- else:
- sys.stderr.write("Not a color: {}\n".format(s))
- raise ValueError
-def bool_correct(s):
- if re.match(r'^false$', s, re.IGNORECASE):
- return False
- elif re.match(r'^true$', s, re.IGNORECASE):
- return True
- else:
- return s
-
-class dotdict(dict):
- """dot.notation access to dictionary attributes"""
- def __getattr__(self, attr):
- return self.get(attr)
- __setattr__= dict.__setitem__
- __delattr__= dict.__delitem__
-
-def get_mimetype(f):
- try:
- mimetype = Popen(
- [BIN_IDENTIFY, f], stdout=PIPE
- ).communicate()[0].split(" ")[1].lower()
- return mimetype
- except Exception as e:
- sys.stderr.write("IMGRID couldn't determine mimetype")
- sys.stderr.write(str(e))
- raise;
-
-def sanitize (str):
- return re.sub(r'\W+', '', str)
-
-def now():
- return int(time.time())
-
-def browser_request (url, data=None):
- headers = {
- 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
- 'Accept': '*/*',
- }
- try:
- req = Request(url, data, headers)
- response = urlopen(req)
- except IOError, e:
- if hasattr(e, 'code'):
- sys.stderr.write( '%s - ERROR %s' % (url, e.code) )
- raise;
- return None
- else:
- return response
-
-def download(url, destination, max_size=MAX_SIZE):
- response = browser_request(url, None)
- rawimg = response.read()
- if len(rawimg) == 0:
- sys.stderr.write("got zero-length file")
- raise;
- if len(rawimg) > max_size:
- sys.stderr.write("file too big: max size {} KB / {} is {} KB".format(
- str(MAX_SIZE/1024),
- destination,
- str(len(rawimg)/1024)
- ))
- raise;
- f = open(destination, "w")
- f.write(rawimg)
- f.close()
-
-def file_size (filepath):
- try:
- return os.stat(file)[6]
- except Exception as e:
- sys.stderr.write("IMGRID couldn't determine file size")
- sys.stderr.write(str(e))
- raise;
-
-def gif_frames(filepath):
- try:
- info = Popen([BIN_IDENTIFY,filepath], stdout=PIPE).communicate()[0]
- frames = filter((lambda x: x), map(
- (lambda x: x.split(" ")[0]),
- (info).split('\n')
- ))
- return frames
- except Exception as e:
- sys.stderr.write("IMGRID couldn't get gif frames")
- sys.stderr.write(str(e))
- raise;
-#}}}
class Imgrid():
- def __init__(self, params):
- self.params = {}
+ def __init__(self, **kwargs):
self.tag = "imGrid"
- self.now = now()
self.files_created = []
self.commands = [];
self._required_keys = [
@@ -160,47 +44,48 @@ class Imgrid():
"username"
#}}}
]
+
+ #Work out params ...
+ #note, tmpfile lib is pretty much useless here, given imagemagick's behavior with gifs (it splits them) etc...
+ #instead we're just making our own in /var/www/cache (tmpfs mounted there)
+ self.params = {}
for k in self._required_keys:
- if k in params:
- if k in [ 'bgimage', 'planebgimage', 'imageinstead' ] and bool_correct(params[k]):
- self.params[k] = {}
- self.params[k]['url'] = params[k]
- self.params[k]['filename'] = "IMGRIDTMP{}_{}".format(now(), k)
-
- self.params[k]['path'] = os.path.join(WORKING_DIR, self.params[k]['filename'])
+ if k in kwargs:
+ if k in [ 'bgimage', 'planebgimage', 'imageinstead' ] and utils.bool_correct(kwargs[k]):
+ self.params[k] = {
+ 'url' : kwargs[k],
+ 'filename' : self._make_tempname(k),
+ 'path' : os.path.join(WORKING_DIR, self._make_tempname(k)) ,
+ }
try:
- download(self.params[k]['url'], self.params[k]['path'])
+ utils.download(self.params[k]['url'], self.params[k]['path'])
self.files_created.append(self.params[k]['path'])
- self.params[k]['mimetype'] = get_mimetype(self.params[k]['path'])
- frames = gif_frames(self.params[k]['path'])
+ self.params[k]['mimetype'] = utils.get_mimetype(self.params[k]['path'])
+ frames = utils.gif_frames(self.params[k]['path'])
if len(frames) > 1:
self.params[k]['path'] = random.choice(frames)
-
- except Exception as e:
- sys.stderr.write("BAD PARAMS\n")
+ except Exception:
sys.stderr.write(str(e))
- raise;
+ raise Exception ("BAD PARAMS");
elif k in [ 'skycolor', 'bgcolor', 'planebgcolor','linecolor' ]:
try:
self.params[k] = is_color(params[k])
- except Exception as e:
- sys.stderr.write("Unable to process color for:\n")
- sys.stderr.write(k)
- raise e
+ except Exception:
+ raise Exception("Unable to process color for:\n{}".format(k))
elif k == 'opacity':
self.params[k] = str(float(params[k]))
elif k == 'zoom':
self.params[k] = int(float(params[k]))
else:
- self.params[k] = bool_correct(sanitize(params[k]))
+ self.params[k] = utils.bool_correct(utils.sanitize(kwargs[k]))
else:
- self.params[k] = False;
-
- self.params = dotdict(self.params)
+ self.params[k] = None;
+
+ self.params = utils.dotdict(self.params)
self.basename = self._get_filename();
-
+
if not self.params.finalformat:
self.params.finalformat = DEFAULT_FINALFORMAT
self.filename = "{}.{}".format(self.basename, self.params.finalformat)
@@ -210,21 +95,20 @@ class Imgrid():
def _get_filename(self):
return "{}_{}_{}".format(
self.tag,
- now(),
+ utils.now(),
self.params.username or ""
);
- def _call_cmd(self, cmd, error=""):
- try:
- call(cmd)
- self.commands.append(" ".join(cmd));
- except Exception as e:
- sys.stderr.write("IT HIT AN ERROR")
- sys.stderr.write(str(cmd))
- if error:
- sys.stderr.write(error)
- else:
- sys.stderr.write(str(e))
+ def _call_cmd(self, cmd):
+ try:
+ utils.call_cmd(cmd)
+ self.commands.append(" ".join(cmd));
+ except Exception:
+ raise Exception("Unable to call cmd {}".format(str(cmd)))
+
+ def _make_tempname(self, s):
+ return "IMGRIDTMP{}{}".format(utils.now(), s);
+
#makes a canvas file...step 1 (if not bgimage)
def _make_canvas(self):
@@ -332,7 +216,7 @@ class Imgrid():
self._cleanup()
if __name__ == "__main__":
- g = Imgrid({
+ g = Imgrid(**{
'bgimage' : 'http://i.asdf.us/im/1a/imBreak_1424909483_xx_abridged___.gif',
'planebgimage' : 'http://i.imgur.com/FICZtph.png',
'tilt' : '30',
@@ -343,6 +227,4 @@ if __name__ == "__main__":
'trim' : 'true'
})
g.create()
- print g.now
- print g.filepath
print g.commands
diff --git a/pb_nginx.conf b/install/pb_nginx.conf
index 994f69a..994f69a 100644
--- a/pb_nginx.conf
+++ b/install/pb_nginx.conf
diff --git a/README.md b/lib/__init__.py
index e69de29..e69de29 100644
--- a/README.md
+++ b/lib/__init__.py
diff --git a/db.py b/lib/db.py
index 2570b4f..2570b4f 100755
--- a/db.py
+++ b/lib/db.py
diff --git a/lib/utils.py b/lib/utils.py
new file mode 100644
index 0000000..a662869
--- /dev/null
+++ b/lib/utils.py
@@ -0,0 +1,122 @@
+import re
+from config import *
+import time
+import urllib
+import urllib2
+import sys
+from subprocess import Popen,PIPE,call
+Request = urllib2.Request
+urlencode = urllib.urlencode
+urlopen = urllib2.urlopen
+
+def call_cmd(cmd, error=""):
+ try:
+ call(cmd)
+ except Exception as e:
+ raise (str(e))
+
+def is_color(s):
+ if s == "":
+ return "transparent"
+ if re.match('(rgba?\([0-9]+,[0-9]+,[0-9]+\))|([a-zA-Z]+)|(\#[A-Ha-h0-9]+)', s):
+ return s.replace(' ', '');
+ else:
+ sys.stderr.write("Not a color: {}\n".format(s))
+ raise ValueError
+
+def dimensions (filepath):
+ #works in lieu of a mimetype check (it reads the header as well)
+ ident = (Popen([BIN_IDENTIFY, filepath], stdout=PIPE).communicate()[0]).split(" ")
+ return ident[2].split("x")
+
+def is_number(s):
+ try:
+ return int(s)
+ except (ValueError, TypeError):
+ return False
+
+def bool_correct(s):
+ if re.match(r'^false$', s, re.IGNORECASE):
+ return False
+ elif re.match(r'^true$', s, re.IGNORECASE):
+ return True
+ else:
+ return s
+
+class dotdict(dict):
+ """dot.notation access to dictionary attributes"""
+ def __getattr__(self, attr):
+ return self.get(attr)
+ __setattr__= dict.__setitem__
+ __delattr__= dict.__delitem__
+
+def get_mimetype(f):
+ try:
+ mimetype = Popen(
+ [BIN_IDENTIFY, f], stdout=PIPE
+ ).communicate()[0].split(" ")[1].lower()
+ return mimetype
+ except Exception as e:
+ sys.stderr.write("couldn't determine mimetype")
+ sys.stderr.write(str(e))
+ raise;
+
+def sanitize (str):
+ return re.sub(r'\W+', '', str)
+
+def now():
+ return int(time.time())
+
+def browser_request (url, data=None):
+ headers = {
+ 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
+ 'Accept': '*/*',
+ }
+ try:
+ req = Request(url, data, headers)
+ response = urlopen(req)
+ except IOError, e:
+ if hasattr(e, 'code'):
+ sys.stderr.write( '%s - ERROR %s' % (url, e.code) )
+ raise;
+ return None
+ else:
+ return response
+
+def download(url, destination, max_size=MAX_SIZE):
+ response = browser_request(url, None)
+ rawimg = response.read()
+ if len(rawimg) == 0:
+ sys.stderr.write("got zero-length file")
+ raise;
+ if len(rawimg) > max_size:
+ sys.stderr.write("file too big: max size {} KB / {} is {} KB".format(
+ str(MAX_SIZE/1024),
+ destination,
+ str(len(rawimg)/1024)
+ ))
+ raise;
+ f = open(destination, "w")
+ f.write(rawimg)
+ f.close()
+
+def file_size (filepath):
+ try:
+ return os.stat(file)[6]
+ except Exception as e:
+ sys.stderr.write("IMGRID couldn't determine file size")
+ sys.stderr.write(str(e))
+ raise;
+
+def gif_frames(filepath):
+ try:
+ info = Popen([BIN_IDENTIFY,filepath], stdout=PIPE).communicate()[0]
+ frames = filter((lambda x: x), map(
+ (lambda x: x.split(" ")[0]),
+ (info).split('\n')
+ ))
+ return frames
+ except Exception as e:
+ sys.stderr.write("IMGRID couldn't get gif frames")
+ sys.stderr.write(str(e))
+ raise;
diff --git a/pattern.py b/pattern.py
index b622aeb..5470004 100755
--- a/pattern.py
+++ b/pattern.py
@@ -1,121 +1,21 @@
#!/usr/bin/python2.7
-from subprocess import call, Popen, PIPE
-import urllib
-import urllib2
import os
import sys
import random
import re
-import time
-urlencode = urllib.urlencode
-urlopen = urllib2.urlopen
-Request = urllib2.Request
+import urllib
+from config import *
+import lib.utils as utils
import simplejson as json
from PIL import Image
import uuid
-WORKING_DIR = "/tmp"
-#WORKING_DIR = "/var/www/cache"
-BIN_COMPOSITE = "/usr/bin/composite"
-BIN_CONVERT = "/usr/bin/convert"
-BIN_IDENTIFY = "/usr/bin/identify"
-DEFAULT_FINALFORMAT = "png";
-
-MAX_SIZE = 1024 * 1024 * 1.2 * 1.5
-
-#FIXME make test params
FUSE_MODE="Pin_Light"
-TEST_PARAMS = {
-# "pattern_url" : "http://asdf.us/impattern/patterns/1.png",
- "pattern_data" : '{"matrix":[["0","0","0","0","0","1","0","0","0","0"],["0","0","0","0","1","1","1","0","0","0"],["0","0","1","1","1","0","1","0","0","0"],["0","1","1","0","0","0","0","0","0","0"],["0","1","0","0","1","0","0","0","0","0"],["0","1","0","0","1","0","0","0","1","0"],["0","1","0","0","1","1","0","0","1","0"],["0","1","0","0","0","1","1","1","1","0"],["0","1","1","1","1","0","0","0","0","0"],["0","0","0","0","1","0","0","0","0","0"]],"width":"10","height":"10"}',
-# "username" : "garfield",
-# "image_url" : "http://i.asdf.us/im/be/PinkHijab_1425078647_reye.gif",
-}
-
-def bool_correct(s):
- if re.match(r'^false$', s, re.IGNORECASE):
- return False
- elif re.match(r'^true$', s, re.IGNORECASE):
- return True
- else:
- return s
-
-#{{{Utility functions
-class dotdict(dict):
- """dot.notation access to dictionary attributes"""
- def __getattr__(self, attr):
- return self.get(attr)
- __setattr__= dict.__setitem__
- __delattr__= dict.__delitem__
-def sanitize (str):
- return re.sub(r'\W+', '', str)
-
-def now():
- return int(time.time())
-
-def browser_request (url, data=None):
- headers = {
- 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)',
- 'Accept': '*/*',
- }
- try:
- req = Request(url, data, headers)
- response = urlopen(req)
- except IOError, e:
- if hasattr(e, 'code'):
- sys.stderr.write( '%s - ERROR %s' % (url, e.code) )
- raise;
- return None
- else:
- return response
-
-def download(url, destination, max_size=MAX_SIZE):
- response = browser_request(url, None)
- rawimg = response.read()
- if len(rawimg) == 0:
- sys.stderr.write("got zero-length file")
- raise;
- if len(rawimg) > max_size:
- sys.stderr.write("file too big: max size {} KB / {} is {} KB".format(
- str(MAX_SIZE/1024),
- destination,
- str(len(rawimg)/1024)
- ))
- raise;
- f = open(destination, "w")
- f.write(rawimg)
- f.close()
-
-def dimensions (filepath):
- #works in lieu of a mimetype check (it reads the header as well)
- ident = (Popen([BIN_IDENTIFY, filepath], stdout=PIPE).communicate()[0]).split(" ")
- return ident[2].split("x")
-
-def file_size (filepath):
- try:
- return os.stat(file)[6]
- except Exception as e:
- sys.stderr.write(str(e))
- raise;
-
-def gif_frames(filepath):
- try:
- info = Popen([BIN_IDENTIFY,filepath], stdout=PIPE).communicate()[0]
- frames = filter((lambda x: x), map(
- (lambda x: x.split(" ")[0]),
- (info).split('\n')
- ))
- return frames
- except Exception as e:
- sys.stderr.write(str(e))
- raise;
-#}}}
class Pattern:
- def __init__(self, params):
+ def __init__(self, **kwargs):
self.params = {}
- self.now = now()
self.tag = "imPattern";
self._pid = str(os.getpid())
self.commands = [];
@@ -131,20 +31,20 @@ class Pattern:
]
self.files_created = []
for k in self._required_keys:
- if k in params:
+ if k in kwargs:
if k in [ 'pattern_url', 'image_url' ]:
- self.params[k] = params[k]
+ self.params[k] = kwargs[k]
elif k == 'pattern_data':
- self.params[k] = params[k] #FIXME add conversion data
+ self.params[k] = kwargs[k] #FIXME add conversion data
else:
- self.params[k] = sanitize(params[k])
+ self.params[k] = utils.sanitize(kwargs[k])
else:
self.params[k] = False;
if not self.params['image_url']:
sys.stderr.write('no image url');
raise ValueError
- self.params = dotdict(self.params)
+ self.params = utils.dotdict(self.params)
self.basename, self._format = self._get_filename();
#FIXME omit file extension for downloaded files
@@ -154,7 +54,7 @@ class Pattern:
self._download(self.params.image_url, self._downloaded_file)
- self.width, self.height = dimensions(self._downloaded_file) # same here
+ self.width, self.height = utils.dimensions(self._downloaded_file) # same here
self.filename = "{}.{}".format(self.basename, self._format)
self.filepath = os.path.join(WORKING_DIR, self.filename)
@@ -169,21 +69,18 @@ class Pattern:
def _download(self, url, dest):
try:
- download(url, dest)
+ utils.download(url, dest)
self.files_created.append(dest)
except Exception as e:
sys.stderr.write(str(e))
raise;
- def _call_cmd(self, cmd, error=""):
- try:
- call(cmd)
- self.commands.append(" ".join(cmd));
- except Exception as e:
- if error:
- sys.stderr.write(error)
- else:
- sys.stderr.write(str(e))
+ def _call_cmd(self, cmd):
+ try:
+ utils.call_cmd(cmd)
+ self.commands.append(" ".join(cmd));
+ except Exception:
+ raise Exception("Unable to call cmd {}".format(str(cmd)))
def _from_pattern_data(self):
def boolToColor(boolean):
@@ -215,8 +112,8 @@ class Pattern:
name_part = url.split("/")[-1]
try:
parts = name_part.split(".")
- name_part = sanitize(parts[-2])
- file_format = sanitize(parts[-1])
+ name_part = utils.sanitize(parts[-2])
+ file_format = utils.sanitize(parts[-1])
if not name_part or not file_format:
sys.stderr.write( "Incompatible input file type")
raise;
@@ -228,7 +125,7 @@ class Pattern:
raise;
if (len(name_part) > 20):
name_part = name_part[:-20]
- return "{}{}_{}_{}".format(self.tag, name_part, self.now, self.params.username or ""), file_format
+ return "{}{}_{}_{}".format(self.tag, name_part, utils.now(), self.params.username or ""), file_format
def _cleanup(self):
cmd = ["rm"]+self.files_created
@@ -263,6 +160,12 @@ class Pattern:
self._fuse_mask();
if __name__ == "__main__":
- p = Pattern(TEST_PARAMS)
+ TEST_PARAMS = {
+ # "pattern_url" : "http://asdf.us/impattern/patterns/1.png",
+ "pattern_data" : '{"matrix":[["0","0","0","0","0","1","0","0","0","0"],["0","0","0","0","1","1","1","0","0","0"],["0","0","1","1","1","0","1","0","0","0"],["0","1","1","0","0","0","0","0","0","0"],["0","1","0","0","1","0","0","0","0","0"],["0","1","0","0","1","0","0","0","1","0"],["0","1","0","0","1","1","0","0","1","0"],["0","1","0","0","0","1","1","1","1","0"],["0","1","1","1","1","0","0","0","0","0"],["0","0","0","0","1","0","0","0","0","0"]],"width":"10","height":"10"}',
+ # "username" : "garfield",
+ "image_url" : "http://i.asdf.us/im/be/PinkHijab_1425078647_reye.gif",
+ }
+ p = Pattern(**TEST_PARAMS)
p.create()
diff --git a/pbserver.py b/pbserver.py
index e7f190a..02a17ed 100755
--- a/pbserver.py
+++ b/pbserver.py
@@ -6,12 +6,11 @@ from imgrid import Imgrid
from breaker import Breaker
from pattern import Pattern
-from s3config import AWS_SECRET_ACCESS_KEY, AWS_ACCESS_KEY_ID, BUCKET_NAME
+from config import AWS_SECRET_ACCESS_KEY, AWS_ACCESS_KEY_ID, BUCKET_NAME
import os
import sys
-import db
-import s3
+import lib.db as db
import mimetypes
import sha
from subprocess import call, Popen, PIPE
@@ -20,12 +19,12 @@ BIN_IDENTIFY = "/usr/bin/identify"
from boto.s3.connection import S3Connection
from boto.s3.key import Key
-
-try:
- DB = db.db ()
-except Exception as e:
- sys.stderr.write("Could not connect to db:\n{}".format(e))
- sys.exit(1);
+#
+#try:
+# DB = db.db ()
+#except Exception as e:
+# sys.stderr.write("Could not connect to db:\n{}".format(e))
+# sys.exit(1);
BASE_URL = "http://i.asdf.us"
def hashdir(filename):
@@ -113,7 +112,7 @@ def return_image(im, insert_url="NULL"):
@post('/im/api/imgradient')
def gradient():
try:
- im = Gradient(request.forms)
+ im = Gradient(**(dict(request.forms)))
im.create();
return return_image(im)
except Exception as e:
diff --git a/s3.py b/s3.py
deleted file mode 100644
index 0f2489d..0000000
--- a/s3.py
+++ /dev/null
@@ -1,618 +0,0 @@
-#!/usr/bin/env python
-
-# This software code is made available "AS IS" without warranties of any
-# kind. You may copy, display, modify and redistribute the software
-# code either by itself or as incorporated into your code; provided that
-# you do not remove any proprietary notices. Your use of this software
-# code is at your own risk and you waive any claim against Amazon
-# Digital Services, Inc. or its affiliates with respect to your use of
-# this software code. (c) 2006-2007 Amazon Digital Services, Inc. or its
-# affiliates.
-
-import base64
-import hmac
-import httplib
-import re
-import sha
-import sys
-import time
-import urllib
-import urlparse
-import xml.sax
-
-DEFAULT_HOST = 's3.amazonaws.com'
-PORTS_BY_SECURITY = { True: 443, False: 80 }
-METADATA_PREFIX = 'x-amz-meta-'
-AMAZON_HEADER_PREFIX = 'x-amz-'
-
-# generates the aws canonical string for the given parameters
-def canonical_string(method, bucket="", key="", query_args={}, headers={}, expires=None):
- interesting_headers = {}
- for header_key in headers:
- lk = header_key.lower()
- if lk in ['content-md5', 'content-type', 'date'] or lk.startswith(AMAZON_HEADER_PREFIX):
- interesting_headers[lk] = headers[header_key].strip()
-
- # these keys get empty strings if they don't exist
- if not interesting_headers.has_key('content-type'):
- interesting_headers['content-type'] = ''
- if not interesting_headers.has_key('content-md5'):
- interesting_headers['content-md5'] = ''
-
- # just in case someone used this. it's not necessary in this lib.
- if interesting_headers.has_key('x-amz-date'):
- interesting_headers['date'] = ''
-
- # if you're using expires for query string auth, then it trumps date
- # (and x-amz-date)
- if expires:
- interesting_headers['date'] = str(expires)
-
- sorted_header_keys = interesting_headers.keys()
- sorted_header_keys.sort()
-
- buf = "%s\n" % method
- for header_key in sorted_header_keys:
- if header_key.startswith(AMAZON_HEADER_PREFIX):
- buf += "%s:%s\n" % (header_key, interesting_headers[header_key])
- else:
- buf += "%s\n" % interesting_headers[header_key]
-
- # append the bucket if it exists
- if bucket != "":
- buf += "/%s" % bucket
-
- # add the key. even if it doesn't exist, add the slash
- buf += "/%s" % urllib.quote_plus(key)
-
- # handle special query string arguments
-
- if query_args.has_key("acl"):
- buf += "?acl"
- elif query_args.has_key("torrent"):
- buf += "?torrent"
- elif query_args.has_key("logging"):
- buf += "?logging"
- elif query_args.has_key("location"):
- buf += "?location"
-
- return buf
-
-# computes the base64'ed hmac-sha hash of the canonical string and the secret
-# access key, optionally urlencoding the result
-def encode(aws_secret_access_key, str, urlencode=False):
- b64_hmac = base64.encodestring(hmac.new(aws_secret_access_key, str, sha).digest()).strip()
- if urlencode:
- return urllib.quote_plus(b64_hmac)
- else:
- return b64_hmac
-
-def merge_meta(headers, metadata):
- final_headers = headers.copy()
- for k in metadata.keys():
- final_headers[METADATA_PREFIX + k] = metadata[k]
-
- return final_headers
-
-# builds the query arg string
-def query_args_hash_to_string(query_args):
- query_string = ""
- pairs = []
- for k, v in query_args.items():
- piece = k
- if v != None:
- piece += "=%s" % urllib.quote_plus(str(v))
- pairs.append(piece)
-
- return '&'.join(pairs)
-
-
-class CallingFormat:
- PATH = 1
- SUBDOMAIN = 2
- VANITY = 3
-
- def build_url_base(protocol, server, port, bucket, calling_format):
- url_base = '%s://' % protocol
-
- if bucket == '':
- url_base += server
- elif calling_format == CallingFormat.SUBDOMAIN:
- url_base += "%s.%s" % (bucket, server)
- elif calling_format == CallingFormat.VANITY:
- url_base += bucket
- else:
- url_base += server
-
- url_base += ":%s" % port
-
- if (bucket != '') and (calling_format == CallingFormat.PATH):
- url_base += "/%s" % bucket
-
- return url_base
-
- build_url_base = staticmethod(build_url_base)
-
-
-
-class Location:
- DEFAULT = None
- EU = 'EU'
-
-
-
-class AWSAuthConnection:
- def __init__(self, aws_access_key_id, aws_secret_access_key, is_secure=True,
- server=DEFAULT_HOST, port=443, calling_format=CallingFormat.SUBDOMAIN):
-
- if not port:
- port = PORTS_BY_SECURITY[is_secure]
-
- self.aws_access_key_id = aws_access_key_id
- self.aws_secret_access_key = aws_secret_access_key
- self.is_secure = is_secure
- self.server = server
- self.port = port
- self.calling_format = calling_format
-
- def create_bucket(self, bucket, headers={}):
- return Response(self._make_request('PUT', bucket, '', {}, headers))
-
- def create_located_bucket(self, bucket, location=Location.DEFAULT, headers={}):
- if location == Location.DEFAULT:
- body = ""
- else:
- body = "<CreateBucketConstraint><LocationConstraint>" + \
- location + \
- "</LocationConstraint></CreateBucketConstraint>"
- return Response(self._make_request('PUT', bucket, '', {}, headers, body))
-
- def check_bucket_exists(self, bucket):
- return self._make_request('HEAD', bucket, '', {}, {})
-
- def list_bucket(self, bucket, options={}, headers={}):
- return ListBucketResponse(self._make_request('GET', bucket, '', options, headers))
-
- def delete_bucket(self, bucket, headers={}):
- return Response(self._make_request('DELETE', bucket, '', {}, headers))
-
- def put(self, bucket, key, object, headers={}):
- if not isinstance(object, S3Object):
- object = S3Object(object)
-
- return Response(
- self._make_request(
- 'PUT',
- bucket,
- key,
- {},
- headers,
- object.data,
- object.metadata))
-
- def get(self, bucket, key, headers={}):
- return GetResponse(
- self._make_request('GET', bucket, key, {}, headers))
-
- def delete(self, bucket, key, headers={}):
- return Response(
- self._make_request('DELETE', bucket, key, {}, headers))
-
- def get_bucket_logging(self, bucket, headers={}):
- return GetResponse(self._make_request('GET', bucket, '', { 'logging': None }, headers))
-
- def put_bucket_logging(self, bucket, logging_xml_doc, headers={}):
- return Response(self._make_request('PUT', bucket, '', { 'logging': None }, headers, logging_xml_doc))
-
- def get_bucket_acl(self, bucket, headers={}):
- return self.get_acl(bucket, '', headers)
-
- def get_acl(self, bucket, key, headers={}):
- return GetResponse(
- self._make_request('GET', bucket, key, { 'acl': None }, headers))
-
- def put_bucket_acl(self, bucket, acl_xml_document, headers={}):
- return self.put_acl(bucket, '', acl_xml_document, headers)
-
- def put_acl(self, bucket, key, acl_xml_document, headers={}):
- return Response(
- self._make_request(
- 'PUT',
- bucket,
- key,
- { 'acl': None },
- headers,
- acl_xml_document))
-
- def list_all_my_buckets(self, headers={}):
- return ListAllMyBucketsResponse(self._make_request('GET', '', '', {}, headers))
-
- def get_bucket_location(self, bucket):
- return LocationResponse(self._make_request('GET', bucket, '', {'location' : None}))
-
- # end public methods
-
- def _make_request(self, method, bucket='', key='', query_args={}, headers={}, data='', metadata={}):
-
- server = ''
- if bucket == '':
- server = self.server
- elif self.calling_format == CallingFormat.SUBDOMAIN:
- server = "%s.%s" % (bucket, self.server)
- elif self.calling_format == CallingFormat.VANITY:
- server = bucket
- else:
- server = self.server
-
- path = ''
-
- if (bucket != '') and (self.calling_format == CallingFormat.PATH):
- path += "/%s" % bucket
-
- # add the slash after the bucket regardless
- # the key will be appended if it is non-empty
- path += "/%s" % urllib.quote_plus(key)
-
-
- # build the path_argument string
- # add the ? in all cases since
- # signature and credentials follow path args
- if len(query_args):
- path += "?" + query_args_hash_to_string(query_args)
-
- is_secure = self.is_secure
- host = "%s:%d" % (server, self.port)
- while True:
- if (is_secure):
- connection = httplib.HTTPSConnection(host)
- else:
- connection = httplib.HTTPConnection(host)
-
- final_headers = merge_meta(headers, metadata);
- # add auth header
- self._add_aws_auth_header(final_headers, method, bucket, key, query_args)
-
- connection.request(method, path, data, final_headers)
- resp = connection.getresponse()
- if resp.status < 300 or resp.status >= 400:
- return resp
- # handle redirect
- location = resp.getheader('location')
- if not location:
- return resp
- # (close connection)
- resp.read()
- scheme, host, path, params, query, fragment \
- = urlparse.urlparse(location)
- if scheme == "http": is_secure = True
- elif scheme == "https": is_secure = False
- else: raise invalidURL("Not http/https: " + location)
- if query: path += "?" + query
- # retry with redirect
-
- def _add_aws_auth_header(self, headers, method, bucket, key, query_args):
- if not headers.has_key('Date'):
- headers['Date'] = time.strftime("%a, %d %b %Y %X GMT", time.gmtime())
-
- c_string = canonical_string(method, bucket, key, query_args, headers)
- headers['Authorization'] = \
- "AWS %s:%s" % (self.aws_access_key_id, encode(self.aws_secret_access_key, c_string))
-
-
-class QueryStringAuthGenerator:
- # by default, expire in 1 minute
- DEFAULT_EXPIRES_IN = 60
-
- def __init__(self, aws_access_key_id, aws_secret_access_key, is_secure=True,
- server=DEFAULT_HOST, port=None, calling_format=CallingFormat.SUBDOMAIN):
-
- if not port:
- port = PORTS_BY_SECURITY[is_secure]
-
- self.aws_access_key_id = aws_access_key_id
- self.aws_secret_access_key = aws_secret_access_key
- if (is_secure):
- self.protocol = 'https'
- else:
- self.protocol = 'http'
-
- self.is_secure = is_secure
- self.server = server
- self.port = port
- self.calling_format = calling_format
- self.__expires_in = QueryStringAuthGenerator.DEFAULT_EXPIRES_IN
- self.__expires = None
-
- # for backwards compatibility with older versions
- self.server_name = "%s:%s" % (self.server, self.port)
-
- def set_expires_in(self, expires_in):
- self.__expires_in = expires_in
- self.__expires = None
-
- def set_expires(self, expires):
- self.__expires = expires
- self.__expires_in = None
-
- def create_bucket(self, bucket, headers={}):
- return self.generate_url('PUT', bucket, '', {}, headers)
-
- def list_bucket(self, bucket, options={}, headers={}):
- return self.generate_url('GET', bucket, '', options, headers)
-
- def delete_bucket(self, bucket, headers={}):
- return self.generate_url('DELETE', bucket, '', {}, headers)
-
- def put(self, bucket, key, object, headers={}):
- if not isinstance(object, S3Object):
- object = S3Object(object)
-
- return self.generate_url(
- 'PUT',
- bucket,
- key,
- {},
- merge_meta(headers, object.metadata))
-
- def get(self, bucket, key, headers={}):
- return self.generate_url('GET', bucket, key, {}, headers)
-
- def delete(self, bucket, key, headers={}):
- return self.generate_url('DELETE', bucket, key, {}, headers)
-
- def get_bucket_logging(self, bucket, headers={}):
- return self.generate_url('GET', bucket, '', { 'logging': None }, headers)
-
- def put_bucket_logging(self, bucket, logging_xml_doc, headers={}):
- return self.generate_url('PUT', bucket, '', { 'logging': None }, headers)
-
- def get_bucket_acl(self, bucket, headers={}):
- return self.get_acl(bucket, '', headers)
-
- def get_acl(self, bucket, key='', headers={}):
- return self.generate_url('GET', bucket, key, { 'acl': None }, headers)
-
- def put_bucket_acl(self, bucket, acl_xml_document, headers={}):
- return self.put_acl(bucket, '', acl_xml_document, headers)
-
- # don't really care what the doc is here.
- def put_acl(self, bucket, key, acl_xml_document, headers={}):
- return self.generate_url('PUT', bucket, key, { 'acl': None }, headers)
-
- def list_all_my_buckets(self, headers={}):
- return self.generate_url('GET', '', '', {}, headers)
-
- def make_bare_url(self, bucket, key=''):
- full_url = self.generate_url(self, bucket, key)
- return full_url[:full_url.index('?')]
-
- def generate_url(self, method, bucket='', key='', query_args={}, headers={}):
- expires = 0
- if self.__expires_in != None:
- expires = int(time.time() + self.__expires_in)
- elif self.__expires != None:
- expires = int(self.__expires)
- else:
- raise "Invalid expires state"
-
- canonical_str = canonical_string(method, bucket, key, query_args, headers, expires)
- encoded_canonical = encode(self.aws_secret_access_key, canonical_str)
-
- url = CallingFormat.build_url_base(self.protocol, self.server, self.port, bucket, self.calling_format)
-
- url += "/%s" % urllib.quote_plus(key)
-
- query_args['Signature'] = encoded_canonical
- query_args['Expires'] = expires
- query_args['AWSAccessKeyId'] = self.aws_access_key_id
-
- url += "?%s" % query_args_hash_to_string(query_args)
-
- return url
-
-
-class S3Object:
- def __init__(self, data, metadata={}):
- self.data = data
- self.metadata = metadata
-
-class Owner:
- def __init__(self, id='', display_name=''):
- self.id = id
- self.display_name = display_name
-
-class ListEntry:
- def __init__(self, key='', last_modified=None, etag='', size=0, storage_class='', owner=None):
- self.key = key
- self.last_modified = last_modified
- self.etag = etag
- self.size = size
- self.storage_class = storage_class
- self.owner = owner
-
-class CommonPrefixEntry:
- def __init(self, prefix=''):
- self.prefix = prefix
-
-class Bucket:
- def __init__(self, name='', creation_date=''):
- self.name = name
- self.creation_date = creation_date
-
-class Response:
- def __init__(self, http_response):
- self.http_response = http_response
- # you have to do this read, even if you don't expect a body.
- # otherwise, the next request fails.
- self.body = http_response.read()
- if http_response.status >= 300 and self.body:
- self.message = self.body
- else:
- self.message = "%03d %s" % (http_response.status, http_response.reason)
-
-
-
-class ListBucketResponse(Response):
- def __init__(self, http_response):
- Response.__init__(self, http_response)
- if http_response.status < 300:
- handler = ListBucketHandler()
- xml.sax.parseString(self.body, handler)
- self.entries = handler.entries
- self.common_prefixes = handler.common_prefixes
- self.name = handler.name
- self.marker = handler.marker
- self.prefix = handler.prefix
- self.is_truncated = handler.is_truncated
- self.delimiter = handler.delimiter
- self.max_keys = handler.max_keys
- self.next_marker = handler.next_marker
- else:
- self.entries = []
-
-class ListAllMyBucketsResponse(Response):
- def __init__(self, http_response):
- Response.__init__(self, http_response)
- if http_response.status < 300:
- handler = ListAllMyBucketsHandler()
- xml.sax.parseString(self.body, handler)
- self.entries = handler.entries
- else:
- self.entries = []
-
-class GetResponse(Response):
- def __init__(self, http_response):
- Response.__init__(self, http_response)
- response_headers = http_response.msg # older pythons don't have getheaders
- metadata = self.get_aws_metadata(response_headers)
- self.object = S3Object(self.body, metadata)
-
- def get_aws_metadata(self, headers):
- metadata = {}
- for hkey in headers.keys():
- if hkey.lower().startswith(METADATA_PREFIX):
- metadata[hkey[len(METADATA_PREFIX):]] = headers[hkey]
- del headers[hkey]
-
- return metadata
-
-class LocationResponse(Response):
- def __init__(self, http_response):
- Response.__init__(self, http_response)
- if http_response.status < 300:
- handler = LocationHandler()
- xml.sax.parseString(self.body, handler)
- self.location = handler.location
-
-class ListBucketHandler(xml.sax.ContentHandler):
- def __init__(self):
- self.entries = []
- self.curr_entry = None
- self.curr_text = ''
- self.common_prefixes = []
- self.curr_common_prefix = None
- self.name = ''
- self.marker = ''
- self.prefix = ''
- self.is_truncated = False
- self.delimiter = ''
- self.max_keys = 0
- self.next_marker = ''
- self.is_echoed_prefix_set = False
-
- def startElement(self, name, attrs):
- if name == 'Contents':
- self.curr_entry = ListEntry()
- elif name == 'Owner':
- self.curr_entry.owner = Owner()
- elif name == 'CommonPrefixes':
- self.curr_common_prefix = CommonPrefixEntry()
-
-
- def endElement(self, name):
- if name == 'Contents':
- self.entries.append(self.curr_entry)
- elif name == 'CommonPrefixes':
- self.common_prefixes.append(self.curr_common_prefix)
- elif name == 'Key':
- self.curr_entry.key = self.curr_text
- elif name == 'LastModified':
- self.curr_entry.last_modified = self.curr_text
- elif name == 'ETag':
- self.curr_entry.etag = self.curr_text
- elif name == 'Size':
- self.curr_entry.size = int(self.curr_text)
- elif name == 'ID':
- self.curr_entry.owner.id = self.curr_text
- elif name == 'DisplayName':
- self.curr_entry.owner.display_name = self.curr_text
- elif name == 'StorageClass':
- self.curr_entry.storage_class = self.curr_text
- elif name == 'Name':
- self.name = self.curr_text
- elif name == 'Prefix' and self.is_echoed_prefix_set:
- self.curr_common_prefix.prefix = self.curr_text
- elif name == 'Prefix':
- self.prefix = self.curr_text
- self.is_echoed_prefix_set = True
- elif name == 'Marker':
- self.marker = self.curr_text
- elif name == 'IsTruncated':
- self.is_truncated = self.curr_text == 'true'
- elif name == 'Delimiter':
- self.delimiter = self.curr_text
- elif name == 'MaxKeys':
- self.max_keys = int(self.curr_text)
- elif name == 'NextMarker':
- self.next_marker = self.curr_text
-
- self.curr_text = ''
-
- def characters(self, content):
- self.curr_text += content
-
-
-class ListAllMyBucketsHandler(xml.sax.ContentHandler):
- def __init__(self):
- self.entries = []
- self.curr_entry = None
- self.curr_text = ''
-
- def startElement(self, name, attrs):
- if name == 'Bucket':
- self.curr_entry = Bucket()
-
- def endElement(self, name):
- if name == 'Name':
- self.curr_entry.name = self.curr_text
- elif name == 'CreationDate':
- self.curr_entry.creation_date = self.curr_text
- elif name == 'Bucket':
- self.entries.append(self.curr_entry)
-
- def characters(self, content):
- self.curr_text = content
-
-
-class LocationHandler(xml.sax.ContentHandler):
- def __init__(self):
- self.location = None
- self.state = 'init'
-
- def startElement(self, name, attrs):
- if self.state == 'init':
- if name == 'LocationConstraint':
- self.state = 'tag_location'
- self.location = ''
- else: self.state = 'bad'
- else: self.state = 'bad'
-
- def endElement(self, name):
- if self.state == 'tag_location' and name == 'LocationConstraint':
- self.state = 'done'
- else: self.state = 'bad'
-
- def characters(self, content):
- if self.state == 'tag_location':
- self.location += content
-
diff --git a/s3config.py b/s3config.py
deleted file mode 100644
index 49357ad..0000000
--- a/s3config.py
+++ /dev/null
@@ -1,3 +0,0 @@
-AWS_ACCESS_KEY_ID = 'AKIAIR53VPBXKJMXZIBA'
-AWS_SECRET_ACCESS_KEY = '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'
-BUCKET_NAME = 'i.asdf.us'