From 31a8ff428869614db3cae06ab24dbdb1e3d98064 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 17 Jul 2010 11:33:08 -0500
Subject: Initial mediagoblin structure
---
.gitignore | 9 +++++++
mediagoblin/__init__.py | 0
mediagoblin/app.py | 64 +++++++++++++++++++++++++++++++++++++++++++++++++
mediagoblin/routing.py | 7 ++++++
mediagoblin/util.py | 11 +++++++++
mediagoblin/views.py | 4 ++++
setup.py | 17 +++++++++++++
7 files changed, 112 insertions(+)
create mode 100644 .gitignore
create mode 100644 mediagoblin/__init__.py
create mode 100644 mediagoblin/app.py
create mode 100644 mediagoblin/routing.py
create mode 100644 mediagoblin/util.py
create mode 100644 mediagoblin/views.py
create mode 100644 setup.py
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..0ed4802a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+dist/
+bin/
+develop-eggs/
+build/
+eggs/
+.installed.cfg
+wsgit.egg-info
+*.pyc
+*.pyo
\ No newline at end of file
diff --git a/mediagoblin/__init__.py b/mediagoblin/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
new file mode 100644
index 00000000..41ab7f20
--- /dev/null
+++ b/mediagoblin/app.py
@@ -0,0 +1,64 @@
+import sys
+import urllib
+
+from webob import Request, exc
+import routes
+
+from mediagoblin import routing, util
+
+
+class Error(Exception): pass
+class ImproperlyConfigured(Error): pass
+
+
+def load_controller(string):
+ module_name, func_name = string.split(':', 1)
+ __import__(module_name)
+ module = sys.modules[module_name]
+ func = getattr(module, func_name)
+ return func
+
+
+class MediagoblinApp(object):
+ """
+ Really basic wsgi app using routes and WebOb.
+ """
+ def __init__(self, user_template_path=None):
+ self.template_env = util.get_jinja_env(user_template_path)
+
+ def __call__(self, environ, start_response):
+ request = Request(environ)
+ path_info = request.path_info
+ route_match = routing.mapping.match(path_info)
+
+ # No matching page?
+ if route_match is None:
+ # Try to do see if we have a match with a trailing slash
+ # added and if so, redirect
+ if not path_info.endswith('/') \
+ and request.method == 'GET' \
+ and routing.mapping.match(path_info + '/'):
+ new_path_info = path_info + '/'
+ if request.GET:
+ new_path_info = '%s?%s' % (
+ new_path_info, urllib.urlencode(request.GET))
+ redirect = exc.HTTPTemporaryRedirect(location=new_path_info)
+ return request.get_response(redirect)(environ, start_response)
+
+ # Okay, no matches. 404 time!
+ return exc.HTTPNotFound()(environ, start_response)
+
+ controller = load_controller(route_match['controller'])
+ request.start_response = start_response
+
+ request.matchdict = route_match
+ request.app = self
+ request.template_env = self.template_env
+ request.urlgen = routes.URLGenerator(routing.mapping, environ)
+
+ return controller(request)(environ, start_response)
+
+
+def paste_app_factory(global_config, **kw):
+ return MediagoblinApp(
+ user_template_path=kw.get('local_templates'))
diff --git a/mediagoblin/routing.py b/mediagoblin/routing.py
new file mode 100644
index 00000000..fec08370
--- /dev/null
+++ b/mediagoblin/routing.py
@@ -0,0 +1,7 @@
+from routes import Mapper
+
+mapping = Mapper()
+mapping.minimization = False
+
+mapping.connect(
+ "index", "/", controller="mediagoblin.views:root_view")
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
new file mode 100644
index 00000000..2af9b380
--- /dev/null
+++ b/mediagoblin/util.py
@@ -0,0 +1,11 @@
+import jinja2
+
+def get_jinja_env(user_template_path=None):
+ if user_template_path:
+ loader = jinja2.ChoiceLoader(
+ [jinja2.FileSystemLoader(user_template_path),
+ jinja2.PackageLoader('mediagoblin', 'templates')])
+ else:
+ loader = jinja2.PackageLoader('mediagoblin', 'templates')
+
+ return jinja2.Environment(loader=loader, autoescape=True)
diff --git a/mediagoblin/views.py b/mediagoblin/views.py
new file mode 100644
index 00000000..1b109453
--- /dev/null
+++ b/mediagoblin/views.py
@@ -0,0 +1,4 @@
+from webob import Response, exc
+
+def root_view(request):
+ return Response("This is the root")
diff --git a/setup.py b/setup.py
new file mode 100644
index 00000000..c19e801f
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,17 @@
+from setuptools import setup, find_packages
+
+import sys
+
+setup(
+ name = "mediagoblin",
+ version = "0.0.1",
+ packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
+ zip_safe=False,
+ license = 'AGPLv3',
+ author = 'Christopher Webber',
+ author_email = 'cwebber@dustycloud.org',
+ entry_points = """\
+ [paste.app_factory]
+ mediagoblin = mediagoblin.app:paste_app_factory
+ """,
+ )
--
cgit v1.2.3
From 73e0dbcca32ed18c0ab63cfde8b34cd112b9e528 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 17 Jul 2010 13:32:57 -0500
Subject: Basic but useless connection to the database
---
mediagoblin/app.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index 41ab7f20..4095acc2 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -3,6 +3,7 @@ import urllib
from webob import Request, exc
import routes
+import pymongo
from mediagoblin import routing, util
@@ -23,8 +24,9 @@ class MediagoblinApp(object):
"""
Really basic wsgi app using routes and WebOb.
"""
- def __init__(self, user_template_path=None):
+ def __init__(self, database, user_template_path=None):
self.template_env = util.get_jinja_env(user_template_path)
+ self.db = database
def __call__(self, environ, start_response):
request = Request(environ)
@@ -60,5 +62,9 @@ class MediagoblinApp(object):
def paste_app_factory(global_config, **kw):
+ connection = pymongo.Connection()
+ db = kw.get('db_name', 'mediagoblin')
+
return MediagoblinApp(
+ db,
user_template_path=kw.get('local_templates'))
--
cgit v1.2.3
From 0f63a9440d440aac04042bd6125c70a2cb8116d7 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 18 Jul 2010 11:20:18 -0500
Subject: A few adustments to the routing and etc
---
mediagoblin/app.py | 7 ++++---
mediagoblin/routing.py | 15 +++++++++++----
2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index 4095acc2..7231b786 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -27,11 +27,12 @@ class MediagoblinApp(object):
def __init__(self, database, user_template_path=None):
self.template_env = util.get_jinja_env(user_template_path)
self.db = database
+ self.routing = routing.get_mapper()
def __call__(self, environ, start_response):
request = Request(environ)
path_info = request.path_info
- route_match = routing.mapping.match(path_info)
+ route_match = self.routing.match(path_info)
# No matching page?
if route_match is None:
@@ -39,7 +40,7 @@ class MediagoblinApp(object):
# added and if so, redirect
if not path_info.endswith('/') \
and request.method == 'GET' \
- and routing.mapping.match(path_info + '/'):
+ and self.routing.match(path_info + '/'):
new_path_info = path_info + '/'
if request.GET:
new_path_info = '%s?%s' % (
@@ -56,7 +57,7 @@ class MediagoblinApp(object):
request.matchdict = route_match
request.app = self
request.template_env = self.template_env
- request.urlgen = routes.URLGenerator(routing.mapping, environ)
+ request.urlgen = routes.URLGenerator(self.routing, environ)
return controller(request)(environ, start_response)
diff --git a/mediagoblin/routing.py b/mediagoblin/routing.py
index fec08370..0b345371 100644
--- a/mediagoblin/routing.py
+++ b/mediagoblin/routing.py
@@ -1,7 +1,14 @@
from routes import Mapper
-mapping = Mapper()
-mapping.minimization = False
+def get_mapper():
+ mapping = Mapper()
+ mapping.minimization = False
-mapping.connect(
- "index", "/", controller="mediagoblin.views:root_view")
+ mapping.connect(
+ "index", "/",
+ controller="mediagoblin.views:root_view")
+ mapping.connect(
+ "test_submit", "/test_submit/",
+ controller="mediagoblin.views:submit_test")
+
+ return mapping
--
cgit v1.2.3
From fbf7880e6873a541da5f45f90d9e0fd31119514a Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 18 Jul 2010 11:22:24 -0500
Subject: Starting with the test submit view using wtforms
---
mediagoblin/templates/mediagoblin/test_submit.html | 18 ++++++++++++
mediagoblin/views.py | 32 ++++++++++++++++++++++
2 files changed, 50 insertions(+)
create mode 100644 mediagoblin/templates/mediagoblin/test_submit.html
diff --git a/mediagoblin/templates/mediagoblin/test_submit.html b/mediagoblin/templates/mediagoblin/test_submit.html
new file mode 100644
index 00000000..0d2fd258
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/test_submit.html
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/mediagoblin/views.py b/mediagoblin/views.py
index 1b109453..ef0fddad 100644
--- a/mediagoblin/views.py
+++ b/mediagoblin/views.py
@@ -1,4 +1,36 @@
from webob import Response, exc
+import wtforms
def root_view(request):
return Response("This is the root")
+
+
+class ImageSubmitForm(wtforms.Form):
+ title = wtforms.TextField(
+ 'Title',
+ [wtforms.validators.Length(min=1, max=500)])
+ description = wtforms.TextAreaField('Description of this work')
+ file = wtforms.FileField('File')
+
+
+def submit_test(request):
+ image_form = ImageSubmitForm(request.POST)
+ if request.method == 'POST' and image_form.validate():
+ # create entry and save in database
+
+ # save file to disk
+ ## TODO
+
+ # resize if necessary
+ ## Hm. This should be done on a separate view?
+
+ # redirect
+ pass
+
+ # render
+ template = request.template_env.get_template(
+ 'mediagoblin/test_submit.html')
+ return Response(
+ template.render(
+ {'request': request,
+ 'image_form': image_form}))
--
cgit v1.2.3
From bda3405342feb7f239ccaa2e7cebe76a48909309 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 18 Jul 2010 15:21:51 -0500
Subject: Still totally useless but at least it writes to the database
---
mediagoblin/app.py | 2 +-
mediagoblin/templates/mediagoblin/test_submit.html | 3 ++-
mediagoblin/views.py | 8 +++++++-
3 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index 7231b786..ef4feae3 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -64,7 +64,7 @@ class MediagoblinApp(object):
def paste_app_factory(global_config, **kw):
connection = pymongo.Connection()
- db = kw.get('db_name', 'mediagoblin')
+ db = connection[kw.get('db_name', 'mediagoblin')]
return MediagoblinApp(
db,
diff --git a/mediagoblin/templates/mediagoblin/test_submit.html b/mediagoblin/templates/mediagoblin/test_submit.html
index 0d2fd258..bf91d26b 100644
--- a/mediagoblin/templates/mediagoblin/test_submit.html
+++ b/mediagoblin/templates/mediagoblin/test_submit.html
@@ -1,6 +1,7 @@
-
{% endblock %}
--
cgit v1.2.3
From 2732c28676f1bd36c17bd1afe30cdd3cae3ceb59 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 23 Apr 2011 13:06:27 -0500
Subject: A stupid success view.
---
mediagoblin/submit/routing.py | 2 ++
.../templates/mediagoblin/submit/success.html | 24 ++++++++++++++++++++++
2 files changed, 26 insertions(+)
create mode 100644 mediagoblin/templates/mediagoblin/submit/success.html
diff --git a/mediagoblin/submit/routing.py b/mediagoblin/submit/routing.py
index b2713540..3f61b1f4 100644
--- a/mediagoblin/submit/routing.py
+++ b/mediagoblin/submit/routing.py
@@ -19,4 +19,6 @@ from routes.route import Route
submit_routes = [
Route('mediagoblin.submit.start', '/',
controller='mediagoblin.submit.views:submit_start'),
+ Route('mediagoblin.submit.success', '/',
+ controller='mediagoblin.submit.views:submit_success'),
]
diff --git a/mediagoblin/templates/mediagoblin/submit/success.html b/mediagoblin/templates/mediagoblin/submit/success.html
new file mode 100644
index 00000000..d38517fa
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/submit/success.html
@@ -0,0 +1,24 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+
+{% block mediagoblin_content %}
+ Woohoo! Submitted!
+{% endblock %}
--
cgit v1.2.3
From e21e7bfeb41a8ed6ab8fa3b27132efd84355ff36 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 23 Apr 2011 13:15:09 -0500
Subject: Enclose queue_file writing in with statement so that it's closed
correctly.
---
mediagoblin/submit/views.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 1d93e070..54201796 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -52,7 +52,8 @@ def submit_start(request):
queue_file = request.app.queue_store.get_file(
queue_filepath, 'wb')
- queue_file.write(request.POST['file'].file.read())
+ with queue_file:
+ queue_file.write(request.POST['file'].file.read())
# Add queued filename to the entry
entry.setdefault('queue_files', []).add(queue_filepath)
--
cgit v1.2.3
From 204392362ffbe94159838cdff6c4d3b6968a003d Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 23 Apr 2011 13:29:15 -0500
Subject: Submission of image works :)
/me pours some sparkling grape juice
---
mediagoblin/submit/routing.py | 2 +-
mediagoblin/submit/views.py | 7 +++----
mediagoblin/templates/mediagoblin/submit/success.html | 2 --
3 files changed, 4 insertions(+), 7 deletions(-)
diff --git a/mediagoblin/submit/routing.py b/mediagoblin/submit/routing.py
index 3f61b1f4..cff28acb 100644
--- a/mediagoblin/submit/routing.py
+++ b/mediagoblin/submit/routing.py
@@ -19,6 +19,6 @@ from routes.route import Route
submit_routes = [
Route('mediagoblin.submit.start', '/',
controller='mediagoblin.submit.views:submit_start'),
- Route('mediagoblin.submit.success', '/',
+ Route('mediagoblin.submit.success', '/success/',
controller='mediagoblin.submit.views:submit_success'),
]
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 54201796..1f55336f 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -27,7 +27,7 @@ def submit_start(request):
"""
First view for submitting a file.
"""
- submit_form = submit_forms.SubmitStartForm()
+ submit_form = submit_forms.SubmitStartForm(request.POST)
if request.method == 'POST' and submit_form.validate():
# create entry and save in database
@@ -56,12 +56,12 @@ def submit_start(request):
queue_file.write(request.POST['file'].file.read())
# Add queued filename to the entry
- entry.setdefault('queue_files', []).add(queue_filepath)
+ entry.setdefault('queue_files', []).append(queue_filepath)
entry.save(validate=True)
# redirect
return exc.HTTPFound(
- location=request.urlgen("mediagoblin.submit.submit_success"))
+ location=request.urlgen("mediagoblin.submit.success"))
# render
template = request.template_env.get_template(
@@ -72,7 +72,6 @@ def submit_start(request):
'submit_form': submit_form}))
-@require_active_login
def submit_success(request):
# render
template = request.template_env.get_template(
diff --git a/mediagoblin/templates/mediagoblin/submit/success.html b/mediagoblin/templates/mediagoblin/submit/success.html
index d38517fa..afc9f9d1 100644
--- a/mediagoblin/templates/mediagoblin/submit/success.html
+++ b/mediagoblin/templates/mediagoblin/submit/success.html
@@ -17,8 +17,6 @@
#}
{% extends "mediagoblin/base.html" %}
-{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
-
{% block mediagoblin_content %}
Woohoo! Submitted!
{% endblock %}
--
cgit v1.2.3
From 03afc828ce11523c46d81c1fa4667ec9604ef528 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 23 Apr 2011 14:13:33 -0500
Subject: Properly require files when users submit
---
mediagoblin/submit/views.py | 72 +++++++++++++++++++++++++--------------------
1 file changed, 40 insertions(+), 32 deletions(-)
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 1f55336f..926c7011 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -15,6 +15,8 @@
# along with this program. If not, see .
+from cgi import FieldStorage
+
from webob import Response, exc
from werkzeug.utils import secure_filename
@@ -30,38 +32,44 @@ def submit_start(request):
submit_form = submit_forms.SubmitStartForm(request.POST)
if request.method == 'POST' and submit_form.validate():
- # create entry and save in database
- entry = request.db.MediaEntry()
- entry['title'] = request.POST['title']
- entry['description'] = request.POST.get(['description'])
- entry['media_type'] = u'image' # heh
- entry['uploader'] = request.user
-
- # Save, just so we can get the entry id for the sake of using
- # it to generate the file path
- entry.save(validate=False)
-
- # Now store generate the queueing related filename
- queue_filepath = request.app.queue_store.get_unique_filepath(
- ['media_entries',
- unicode(request.user['_id']),
- unicode(entry['_id']),
- secure_filename(request.POST['file'].filename)])
-
- # queue appropriately
- queue_file = request.app.queue_store.get_file(
- queue_filepath, 'wb')
-
- with queue_file:
- queue_file.write(request.POST['file'].file.read())
-
- # Add queued filename to the entry
- entry.setdefault('queue_files', []).append(queue_filepath)
- entry.save(validate=True)
-
- # redirect
- return exc.HTTPFound(
- location=request.urlgen("mediagoblin.submit.success"))
+ if not (request.POST.has_key('file')
+ and isinstance(request.POST['file'], FieldStorage)
+ and request.POST['file'].file):
+ submit_form.file.errors.append(
+ u'You must provide a file.')
+ else:
+ # create entry and save in database
+ entry = request.db.MediaEntry()
+ entry['title'] = request.POST['title']
+ entry['description'] = request.POST.get(['description'])
+ entry['media_type'] = u'image' # heh
+ entry['uploader'] = request.user
+
+ # Save, just so we can get the entry id for the sake of using
+ # it to generate the file path
+ entry.save(validate=False)
+
+ # Now store generate the queueing related filename
+ queue_filepath = request.app.queue_store.get_unique_filepath(
+ ['media_entries',
+ unicode(request.user['_id']),
+ unicode(entry['_id']),
+ secure_filename(request.POST['file'].filename)])
+
+ # queue appropriately
+ queue_file = request.app.queue_store.get_file(
+ queue_filepath, 'wb')
+
+ with queue_file:
+ queue_file.write(request.POST['file'].file.read())
+
+ # Add queued filename to the entry
+ entry.setdefault('queue_files', []).append(queue_filepath)
+ entry.save(validate=True)
+
+ # redirect
+ return exc.HTTPFound(
+ location=request.urlgen("mediagoblin.submit.success"))
# render
template = request.template_env.get_template(
--
cgit v1.2.3
From 6bcab715b86dabe20aef7ba07960d50e4913ee15 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 24 Apr 2011 10:04:53 -0500
Subject: Time to require celery!
---
setup.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/setup.py b/setup.py
index b47be4c3..38f1a4d4 100644
--- a/setup.py
+++ b/setup.py
@@ -36,6 +36,7 @@ setup(
'py-bcrypt',
'nose',
'werkzeug',
+ 'celery',
],
test_suite='nose.collector',
--
cgit v1.2.3
From df9809c2098d18b0272c40154b5e40d67b703214 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 24 Apr 2011 14:48:55 -0500
Subject: Make certain bits of info accessable as global variables from
anywhere
---
mediagoblin/app.py | 10 ++++++++++
mediagoblin/globals.py | 24 ++++++++++++++++++++++++
mediagoblin/tests/test_globals.py | 29 +++++++++++++++++++++++++++++
3 files changed, 63 insertions(+)
create mode 100644 mediagoblin/globals.py
create mode 100644 mediagoblin/tests/test_globals.py
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index ae6db8f7..78ad19a4 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -21,6 +21,7 @@ import mongokit
from webob import Request, exc
from mediagoblin import routing, util, models, storage, staticdirect
+from mediagoblin.globals import setup_globals
class Error(Exception): pass
@@ -53,6 +54,15 @@ class MediaGoblinApp(object):
# set up staticdirector tool
self.staticdirector = staticdirector
+ # certain properties need to be accessed globally eg from
+ # validators, etc, which might not access to the request
+ # object.
+ setup_globals(
+ db_connection=connection,
+ database=self.db,
+ public_store=self.public_store,
+ queue_store=self.queue_store)
+
def __call__(self, environ, start_response):
request = Request(environ)
path_info = request.path_info
diff --git a/mediagoblin/globals.py b/mediagoblin/globals.py
new file mode 100644
index 00000000..59a94558
--- /dev/null
+++ b/mediagoblin/globals.py
@@ -0,0 +1,24 @@
+"""
+In some places, we need to access the database, public_store, queue_store
+"""
+
+#############################
+# General mediagoblin globals
+#############################
+
+# mongokit.Connection
+db_connection = None
+
+# mongokit.Connection
+database = None
+
+# should be the same as the
+public_store = None
+queue_store = None
+
+
+def setup_globals(**kwargs):
+ from mediagoblin import globals as mg_globals
+
+ for key, value in kwargs.iteritems():
+ setattr(mg_globals, key, value)
diff --git a/mediagoblin/tests/test_globals.py b/mediagoblin/tests/test_globals.py
new file mode 100644
index 00000000..6d2e01da
--- /dev/null
+++ b/mediagoblin/tests/test_globals.py
@@ -0,0 +1,29 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+from mediagoblin import globals as mg_globals
+
+def test_setup_globals():
+ mg_globals.setup_globals(
+ db_connection='my favorite db_connection!',
+ database='my favorite database!',
+ public_store='my favorite public_store!',
+ queue_store='my favorite queue_store!')
+
+ assert mg_globals.db_connection == 'my favorite db_connection!'
+ assert mg_globals.database == 'my favorite database!'
+ assert mg_globals.public_store == 'my favorite public_store!'
+ assert mg_globals.queue_store == 'my favorite queue_store!'
--
cgit v1.2.3
From 5740a0d6aa8647c182c39680fecf6b902485a9b2 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sun, 24 Apr 2011 18:50:48 -0400
Subject: Updates to hacking howto
* adds "what's where" section which isn't wildly interesting right now
but it's somewhat interesting
* adds "wiping environment" section
---
docs/hackinghowto.rst | 46 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 96a7e1a4..50c59d08 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -41,7 +41,8 @@ If you're running Debian GNU/Linux or a Debian-derived distribution
such as Mint or Ubuntu, running the following should install these
requirements::
- sudo apt-get install mongodb git-core python python-dev python-lxml
+ sudo apt-get install mongodb git-core python python-dev \
+ python-lxml
Running bootstrap and buildout
@@ -78,11 +79,26 @@ Updating dependencies
---------------------
While hacking on GNU MediaGoblin over time, you'll eventually have to
-update the dependencies. To do that, run::
+update your development environment. To do that, run::
./bin/buildout
+Wiping your environment for a clean-slate
+-----------------------------------------
+
+Delete the following directories:
+
+* bin/
+* develop-eggs/
+* eggs/
+* mediagoblin.egg-info/
+* parts/
+* user_dev/
+
+FIXME - how to drop data from mongodb?
+
+
Running the server
==================
@@ -99,6 +115,32 @@ Run::
./bin/nosetests
+What's where
+============
+
+After you've run buildout, you're faced with the following directory
+tree::
+
+ mediagoblin/
+ |- mediagoblin/ source code
+ | |- tests/
+ | |- templates/
+ | |- auth/
+ | \- submit/
+ |- docs/ documentation
+ |
+ | the rest of these directories are generated by
+ | buildout.
+ |
+ |- bin/ scripts
+ |- develop-eggs/
+ |- eggs/
+ |- mediagoblin.egg-info/
+ |- parts/
+ |- user_dev/ sessions, etc
+
+
+
Quickstart for Django programmers
=================================
--
cgit v1.2.3
From cafc7451ccdf0dc1d86eba92f3f75254c367d2f7 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sun, 24 Apr 2011 18:55:07 -0400
Subject: Minor tweaks to design decisions text
---
docs/designdecisions.rst | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/docs/designdecisions.rst b/docs/designdecisions.rst
index 6156d523..3398c24b 100644
--- a/docs/designdecisions.rst
+++ b/docs/designdecisions.rst
@@ -17,11 +17,11 @@ Chris Webber on "Why Python":
software web applications before in Python, including `Miro
Community`_, the `Miro Guide`_, a large portion of `Creative
Commons`_, and a whole bunch of things while working at `Imaginary
- Landscape`_). I know Python, I can make this happen in Python, me
- starting a project like this makes sense if it's done in Python.
+ Landscape`_). Me starting a project like this makes sense if it's
+ done in Python.
You might say that PHP is way more deployable, that Rails has way
- more cool developers riding around on fixie bikes, and all of
+ more cool developers riding around on fixie bikes---and all of
those things are true. But I know Python, like Python, and think
that Python is pretty great. I do think that deployment in Python
is not as good as with PHP, but I think the days of shared hosting
@@ -159,14 +159,16 @@ Why Sphinx for documentation
Will Kahn-Greene on "Why Sphinx":
- Sphinx is a fantastic tool for organizing documentation for a
+ `Sphinx`_ is a fantastic tool for organizing documentation for a
Python-based project that makes it pretty easy to write docs that
are readable in source form and can be "compiled" into HTML, LaTeX
and other formats.
There are other doc systems out there, but given that GNU
- MediaGoblin is being written in Python, it makes sense to use
- Sphinx for now.
+ MediaGoblin is being written in Python and I've done a ton of
+ documentation using Sphinx, it makes sense to use Sphinx for now.
+
+.. _Sphinx: http://sphinx.pocoo.org/
Why AGPLv3 and CC0?
--
cgit v1.2.3
From 34366952a21f040ee5ca3df899a82f9e6bd9cffe Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sun, 24 Apr 2011 19:46:48 -0400
Subject: Heavy documentation updates
* Nixed codedocs and software stack chapters in favor of a chapter on
Beardomatic!
* Switched workflow to vision and added an additional caveat at the top
---
docs/beardomatic.rst | 84 +++++++++++++++++++++++++++++
docs/codedocs.rst | 5 --
docs/index.rst | 5 +-
docs/softwarestack.rst | 127 -------------------------------------------
docs/vision.rst | 142 +++++++++++++++++++++++++++++++++++++++++++++++++
docs/workflow.rst | 136 ----------------------------------------------
6 files changed, 228 insertions(+), 271 deletions(-)
create mode 100644 docs/beardomatic.rst
delete mode 100644 docs/codedocs.rst
delete mode 100644 docs/softwarestack.rst
create mode 100644 docs/vision.rst
delete mode 100644 docs/workflow.rst
diff --git a/docs/beardomatic.rst b/docs/beardomatic.rst
new file mode 100644
index 00000000..5ebeb239
--- /dev/null
+++ b/docs/beardomatic.rst
@@ -0,0 +1,84 @@
+===========================================
+ Beardomatic: Infrastructure Documentation
+===========================================
+
+What the hell is Beardomatic?
+=============================
+
+You might be wondering, "Gah! What the hell is Beardomatic!?"
+
+Well, I'll tell you. GNU MediaGoblin is a piece of software that sits
+on a stack of libraries that do a bunch of stuff. It makes it easier
+to differentiate the bits of code that encompass GNU MediaGoblin from
+the bits of code that GNU MediaGoblin sit on top of. Thus, we came up
+with the TOTALLY AWESOME name Beardomatic.
+
+Now you might be saying, "Holy crap!? Another web framework? Are you
+going to write a mocking framework and an enumeration library, too!?"
+
+No, we're not. We're just calling this Beardomatic so that it's
+easier to talk about things. However, at some point, we can take
+these infrastructure bits from GNU MediaGoblin and turn them into a
+full-blown "web framework". We wouldn't do this to compete for
+mindshare with other web frameworks. We would do this to make it
+easier for us to bootstrap other similar projects.
+
+
+Beardomatic software stack
+==========================
+
+Beardomatic is a software stack "web framework" composed of the
+following bits:
+
+* Project infrastructure
+
+ * `Python `_: the language we're using to write
+ this
+
+ * `Nose `_:
+ for unit tests
+
+ * `buildout `_: for getting dependencies,
+ building a runtime environment, ...
+
+* Data storage
+
+ * `MongoDB `_: the document database backend
+ for storage
+
+* Web application
+
+ * `Paste Deploy `_ and
+ `Paste Script `_: we'll use this for
+ configuring and launching the application
+
+ * `WebOb `_: nice abstraction layer
+ from HTTP requests, responses and WSGI bits
+
+ * `Routes `_: for URL routing
+
+ * `Beaker `_: for handling sessions
+
+ * `Jinja2 `_: the templating engine
+
+ * `MongoKit `_: the lightweight
+ ORM for MongoDB we're using which will make it easier to define
+ structures and all that
+
+ * `WTForms `_: for handling,
+ validation, and abstraction from HTML forms
+
+ * `Celery `_: for task queuing (resizing
+ images, encoding video, ...)
+
+ * `RabbitMQ `_: for sending tasks to celery
+
+* Front end
+
+ * `JQuery `_: for groovy JavaScript things
+
+
+How to ... in Beardomatic?
+==========================
+
+FIXME - write this
diff --git a/docs/codedocs.rst b/docs/codedocs.rst
deleted file mode 100644
index 09f91274..00000000
--- a/docs/codedocs.rst
+++ /dev/null
@@ -1,5 +0,0 @@
-====================
- Code Documentation
-====================
-
-FIXME - stub!
diff --git a/docs/index.rst b/docs/index.rst
index fb92d139..fc8cc642 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -17,10 +17,9 @@ Table of Contents:
deploymenthowto
hackinghowto
theminghowto
- softwarestack
designdecisions
- workflow
- codedocs
+ vision
+ beardomatic
Indices and tables
diff --git a/docs/softwarestack.rst b/docs/softwarestack.rst
deleted file mode 100644
index 024f0d5d..00000000
--- a/docs/softwarestack.rst
+++ /dev/null
@@ -1,127 +0,0 @@
-=======
- Stack
-=======
-
-The software stack for this project might change over time, but this
-is what we're thinking right now.
-
-There's some explanation of design decisions in the
-:ref:`design-decisions-chapter`.
-
-
-Python
-======
-
-* http://python.org/
-
-The core team does a lot of work in Python and it's the language we're
-most likely to do a project like this in.
-
-
-MongoDB
-=======
-
-* http://www.mongodb.org/
-
-A "document database". Because it's extremely flexible and scales up
-well, but I guess not down well.
-
-
-MongoKit
-========
-
-* http://namlook.github.com/mongokit/
-
-A lightweight ORM for mongodb. Helps us define our structures better,
-does schema validation, schema evolution, and helps make things more
-fun and pythonic.
-
-
-Jinja2
-======
-
-* http://jinja.pocoo.org/docs/
-
-For templating. Pretty much django templates++ but allows us to pass
-arguments into method calls instead of writing custom tags.
-
-
-WTForms
-=======
-
-* http://wtforms.simplecodes.com/
-
-For form handling, validation, abstraction. Almost just like Django's
-templates.
-
-
-WebOb
-=====
-
-* http://pythonpaste.org/webob/
-
-Gives nice request/response objects (also somewhat Django-ish).
-
-
-Paste Deploy and Paste Script
-=============================
-
-* http://pythonpaste.org/deploy/
-* http://pythonpaste.org/script/
-
-This will be the default way of configuring and launching the
-application. Since GNU MediaGoblin will be fairly WSGI minimalist though,
-you can probably use other ways to launch it, though this will be the
-default.
-
-
-Routes
-======
-
-* http://routes.groovie.org/
-
-For URL Routing. It works well enough.
-
-
-JQuery
-======
-
-* http://jquery.com/
-
-For all sorts of things on the JavaScript end of things, for all sorts
-of reasons.
-
-
-Beaker
-======
-
-* http://beaker.groovie.org/
-
-For sessions, because that seems like it's generally considered the
-way to go I guess.
-
-
-Nose
-====
-
-* http://somethingaboutorange.com/mrl/projects/nose/1.0.0/
-
-For unit tests because it makes testing a bit nicer.
-
-
-Celery
-======
-
-* http://celeryproject.org/
-
-For task queueing (resizing images, encoding video, ...).
-
-
-RabbitMQ
-========
-
-* http://www.rabbitmq.com/
-
-For sending tasks to celery, because I guess that's what most people
-do. Might be optional, might also let people use MongoDB for this if
-they want.
diff --git a/docs/vision.rst b/docs/vision.rst
new file mode 100644
index 00000000..fad248df
--- /dev/null
+++ b/docs/vision.rst
@@ -0,0 +1,142 @@
+=========================================
+ Design Document: GNU MediaGoblin vision
+=========================================
+
+.. Note::
+
+ When we get a wiki, this will get moved there. It's here for now
+ mostly because we didn't have a better place for it.
+
+.. Note::
+
+ By the time you read this, it's very likely it'll be out of date.
+
+
+This document attempts to describe the envisioned workflow of GNU
+MediaGoblin, from a structural standpoint. For now, *nothing* in this
+document is probably the eventual, final way that things will work.
+Eventually as things come to exist, this document will hopefully be
+refactored to describe how things *do* work.
+
+This documented on hopes, dreams, rainbows, and unicorns. And it will
+come to fulfillment through a lot of hard work. Your hard work and my
+hard work.
+
+
+Look and feel
+=============
+
+Default look and feel
+---------------------
+
+Mairin Duffy made mockups for something called Design Hub. That
+project did a number of things differently than the way we intend to
+go, but it's probably a good idea to steal a good number of ideas from
+here.
+
+http://mairin.wordpress.com/2010/03/09/another-design-hub-mockup/
+
+
+User profile mockup
+-------------------
+
+Here's an ascii art mockup on how things might look for a user's page::
+
+ _____
+ |_( )_| USER NAME
+ | | |
+ |_/_\_|
+
+ Recent artwork:
+ ___________________ ___________________________
+ | ___ ___ ___ | |_About_User_Name___________|
+ | |pic| |pic| |pic| | | |
+ | |___| |___| |___| | | Some sort of self- |
+ | ___ ___ ___ | | description probably goes |
+ < | |pic| |pic| |pic| | > | here |
+ | |___| |___| |___| | | |
+ | ___ ___ ___ | | |
+ | |pic| |pic| |pic| | | |
+ | |___| |___| |___| | | |
+ |___________________| |___________________________|
+
+ ___________________________
+ Recent favorites: |_Recent_activity___________|
+ ___________________ | New picture: DragonFace |
+ | ___ ___ ___ | | 4/2/2010 |
+ | |pic| |pic| |pic| | |---------------------------|
+ | |___| |___| |___| | | Sup yall this is some kind|
+ | ___ ___ ___ | | of mini blogpost. Maybe |
+ < | |pic| |pic| |pic| | > | the interface will allow |
+ | |___| |___| |___| | | for this? |
+ | ___ ___ ___ | |___________________________|
+ | |pic| |pic| |pic| |
+ | |___| |___| |___| | ___________________________
+ |___________________| |_External_comments_here____|
+ | Dang! This stuff rocks |
+ | - Joe 4/2/2010 |
+ |---------------------------|
+ | Nice job on the dragon |
+ | - Morgan 4/2/2010 |
+ '---------------------------'
+
+So there's this type of interface that puts a lot of different types
+of info on the same screen. I'm not sure that I like it. It's
+possible we'll go with something much more minimalist. Maybe we'll go
+with something "tabbed" the way statusnet / http://identi.ca is on
+user pages.
+
+It's possible that we could support multiple profile styles here,
+and you could load whatever profile style you want as set by user
+preferences?
+
+
+Uploading mockup
+----------------
+
+Here's an uploading mockup::
+
+ Upload an image
+
+ [ Title ]
+
+ Upload: [ ] [Browse]
+ ___________________________________________
+ | |
+ | |
+ | o0O |
+ | o ' |
+ | o_.' |
+ | |
+ | Uploading... OK | <-,
+ | Resizing... OK | |
+ | | Area replaced w/ resized
+ | | image when done
+ |___________________________________________|
+ ________________
+ License |_CC BY-SA_____|V|
+ ___________________________________________
+ | Description goes here. |
+ | You can type it up in here and everything |
+ | and it'll show up under the image. |
+ | |
+ | Possibly we should allow some kind of |
+ | markup... maybe markdown? |
+ '___________________________________________'
+
+ __________________________________________
+ |> Advanced |
+ ------------------------------------------
+
+
+Customizability
+---------------
+
+General site theming customizability is pretty easy! Since we're
+using `Jinja `_ we can just set up
+user-overriding directories.
+
+We'll also figure out some sort of way to provide theming "packages",
+eventually.
+
+
diff --git a/docs/workflow.rst b/docs/workflow.rst
deleted file mode 100644
index b72031de..00000000
--- a/docs/workflow.rst
+++ /dev/null
@@ -1,136 +0,0 @@
-==========================================================================
- Design Document: Workflow, and other structurally significant braindumps
-==========================================================================
-
-.. Note::
-
- When we get a wiki, this will get moved there. It's here for now
- mostly because we didn't have a better place for it.
-
-
-This document attempts to describe the envisioned workflow of
-mediagoblin, from a structural standpoint. For now, *nothing* in this
-document is probably the eventual, final way that things will work.
-Eventually as things come to exist, this document will hopefully be
-refactored to describe how things *do* work.
-
-This documented on hopes, dreams, rainbows, and unicorns. And it will
-come to fulfillment through a lot of hard work.
-
-
-Look and feel
-=============
-
-Default look and feel
----------------------
-
-Mairin Duffy made mockups for something called Design Hub. That
-project did a number of things differently than the way we intend to
-go, but it's probably a good idea to steal a good number of ideas from
-here.
-
-http://mairin.wordpress.com/2010/03/09/another-design-hub-mockup/
-
-User profile mockup
--------------------
-
-Here's an ascii art mockup on how things might look for a user's page::
-
- _____
- |_( )_| USER NAME
- | | |
- |_/_\_|
-
- Recent artwork:
- ___________________ ___________________________
- | ___ ___ ___ | |_About_User_Name___________|
- | |pic| |pic| |pic| | | |
- | |___| |___| |___| | | Some sort of self- |
- | ___ ___ ___ | | description probably goes |
- < | |pic| |pic| |pic| | > | here |
- | |___| |___| |___| | | |
- | ___ ___ ___ | | |
- | |pic| |pic| |pic| | | |
- | |___| |___| |___| | | |
- |___________________| |___________________________|
-
- ___________________________
- Recent favorites: |_Recent_activity___________|
- ___________________ | New picture: DragonFace |
- | ___ ___ ___ | | 4/2/2010 |
- | |pic| |pic| |pic| | |---------------------------|
- | |___| |___| |___| | | Sup yall this is some kind|
- | ___ ___ ___ | | of mini blogpost. Maybe |
- < | |pic| |pic| |pic| | > | the interface will allow |
- | |___| |___| |___| | | for this? |
- | ___ ___ ___ | |___________________________|
- | |pic| |pic| |pic| |
- | |___| |___| |___| | ___________________________
- |___________________| |_External_comments_here____|
- | Dang! This stuff rocks |
- | - Joe 4/2/2010 |
- |---------------------------|
- | Nice job on the dragon |
- | - Morgan 4/2/2010 |
- '---------------------------'
-
-So there's this type of interface that puts a lot of different types
-of info on the same screen. I'm not sure that I like it. It's
-possible we'll go with something much more minimalist. Maybe we'll go
-with something "tabbed" the way statusnet / http://identi.ca is on
-user pages.
-
-It's possible that we could support multiple profile styles here,
-and you could load whatever profile style you want as set by user
-preferences?
-
-
-Uploading mockup
-----------------
-
-Here's an uploading mockup::
-
- Upload an image
-
- [ Title ]
-
- Upload: [ ] [Browse]
- ___________________________________________
- | |
- | |
- | o0O |
- | o ' |
- | o_.' |
- | |
- | Uploading... OK | <-,
- | Resizing... OK | |
- | | Area replaced w/ resized
- | | image when done
- |___________________________________________|
- ________________
- License |_CC BY-SA_____|V|
- ___________________________________________
- | Description goes here. |
- | You can type it up in here and everything |
- | and it'll show up under the image. |
- | |
- | Possibly we should allow some kind of |
- | markup... maybe markdown? |
- '___________________________________________'
-
- __________________________________________
- |> Advanced |
- ------------------------------------------
-
-
-Customizability
----------------
-
-General site theming customizability is pretty easy! Since we're
-using `Jinja `_ we can just set up
-user-overriding directories.
-
-We'll also figure out some sort of way to provide theming "packages",
-eventually.
-
-
--
cgit v1.2.3
From e231d9e8bb8c5bf6f0705b47592c9aadaf2eb269 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 24 Apr 2011 18:47:23 -0500
Subject: setup_celery_from_config tool. Haven't tried if it works, but looks
right...
---
mediagoblin/celery_setup/__init__.py | 121 +++++++++++++++++++++++++++++++++++
1 file changed, 121 insertions(+)
create mode 100644 mediagoblin/celery_setup/__init__.py
diff --git a/mediagoblin/celery_setup/__init__.py b/mediagoblin/celery_setup/__init__.py
new file mode 100644
index 00000000..171b9a6f
--- /dev/null
+++ b/mediagoblin/celery_setup/__init__.py
@@ -0,0 +1,121 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import os
+
+from paste.deploy.converters import asbool, asint, aslist
+
+
+KNOWN_CONFIG_BOOLS = [
+ 'CELERY_RESULT_PERSISTENT',
+ 'CELERY_CREATE_MISSING_QUEUES',
+ 'BROKER_USE_SSL', 'BROKER_CONNECTION_RETRY',
+ 'CELERY_ALWAYS_EAGER', 'CELERY_EAGER_PROPAGATES_EXCEPTIONS',
+ 'CELERY_IGNORE_RESULT', 'CELERY_TRACK_STARTED',
+ 'CELERY_DISABLE_RATE_LIMITS', 'CELERY_ACKS_LATE',
+ 'CELERY_STORE_ERRORS_EVEN_IF_IGNORED',
+ 'CELERY_SEND_TASK_ERROR_EMAILS',
+ 'CELERY_SEND_EVENTS', 'CELERY_SEND_TASK_SENT_EVENT',
+ 'CELERYD_LOG_COLOR', 'CELERY_REDIRECT_STDOUTS',
+ ]
+
+KNOWN_CONFIG_INTS = [
+ 'CELERYD_CONCURRENCY',
+ 'CELERYD_PREFETCH_MULTIPLIER',
+ 'CELERY_AMQP_TASK_RESULT_EXPIRES',
+ 'CELERY_AMQP_TASK_RESULT_CONNECTION_MAX',
+ 'REDIS_PORT', 'REDIS_DB',
+ 'BROKER_PORT', 'BROKER_CONNECTION_TIMEOUT',
+ 'CELERY_BROKER_CONNECTION_MAX_RETRIES',
+ 'CELERY_TASK_RESULT_EXPIRES', 'CELERY_MAX_CACHED_RESULTS',
+ 'CELERY_DEFAULT_RATE_LIMIT', # ??
+ 'CELERYD_MAX_TASKS_PER_CHILD', 'CELERYD_TASK_TIME_LIMIT',
+ 'CELERYD_TASK_SOFT_TIME_LIMIT',
+ 'MAIL_PORT', 'CELERYBEAT_MAX_LOOP_INTERVAL',
+ ]
+
+KNOWN_CONFIG_FLOATS = [
+ 'CELERYD_ETA_SCHEDULER_PRECISION',
+ ]
+
+KNOWN_CONFIG_LISTS = [
+ 'CELERY_ROUTES', 'CELERY_IMPORTS',
+ ]
+
+
+## Needs special processing:
+# ADMINS, ???
+# there are a lot more; we should list here or process specially.
+
+
+def asfloat(obj):
+ try:
+ return float(obj)
+ except (TypeError, ValueError), e:
+ raise ValueError(
+ "Bad float value: %r" % obj)
+
+
+def setup_celery_from_config(app_config, global_config):
+ """
+ Take a mediagoblin app config and the global config from a paste
+ factory and try to set up a celery settings module from this.
+ """
+ if asbool(app_config.get('use_celery_environment_var')) == True:
+ # Don't setup celery based on our config file.
+ return
+
+ celery_conf_section = app_config.get('celery_section', 'celery')
+ if global_config.has_key(celery_conf_section):
+ celery_conf = global_config[celery_conf_section]
+ else:
+ celery_conf = {}
+
+ celery_settings = {}
+
+ # set up mongodb stuff
+ celery_mongo_settings = {}
+ if app_config.has_key('db_host'):
+ celery_mongo_settings['host'] = app_config['db_host']
+ celery_settings['BROKER_HOST'] = app_config['db_host']
+ if app_config.has_key('db_port'):
+ celery_mongo_settings['port'] = asint(app_config['db_port'])
+ celery_settings['BROKER_PORT'] = asint(app_config['db_port'])
+ celery_mongo_settings['database'] = app_config.get('db_name', 'mediagoblin')
+
+ celery_settings['CELERY_MONGODB_BACKEND_SETTINGS'] = celery_mongo_settings
+ celery_settings['CELERY_RESULT_BACKEND'] = 'mongodb'
+
+ # Add anything else
+ for key, value in celery_conf.iteritems():
+ key = key.upper()
+ if key in KNOWN_CONFIG_BOOLS:
+ value = asbool(value)
+ elif value in KNOWN_CONFIG_INTS:
+ value = asint(value)
+ elif value in KNOWN_CONFIG_FLOATS:
+ value = asfloat(value)
+ elif value in KNOWN_CONFIG_LISTS:
+ value = aslist(value)
+ celery_settings[key] = value
+
+ from mediagoblin.celery_setup import dummy_settings_module
+
+ for key, value in celery_settings.iteritems():
+ setattr(dummy_settings_module, key, value)
+
+ os.environ['CELERY_CONFIG_MODULE'] = \
+ 'mediagoblin.celery_setup.dummy_settings_module'
--
cgit v1.2.3
From 427ee0de13951a66d684d2a6afe33f45df7966b4 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sun, 24 Apr 2011 21:19:00 -0400
Subject: Adds Matt to docs contributors list
---
docs/foreward.rst | 1 +
1 file changed, 1 insertion(+)
diff --git a/docs/foreward.rst b/docs/foreward.rst
index 0a3630a1..c1d60587 100644
--- a/docs/foreward.rst
+++ b/docs/foreward.rst
@@ -26,6 +26,7 @@ In no particular order:
* Deb
* Greg
* Karen
+* Matt
How should I bring up errors in the documentation
--
cgit v1.2.3
From 81be691a20edaeffc27d1cc160e0576ae5f9cd51 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sun, 24 Apr 2011 21:29:39 -0400
Subject: Changes version to 0.0.1.
---
docs/conf.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/conf.py b/docs/conf.py
index 02c190a0..6030b74d 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -48,9 +48,9 @@ copyright = u'2011, Chris Webber, et al'
# built documents.
#
# The short X.Y version.
-version = '0.1a1'
+version = '0.0.1'
# The full version, including alpha/beta/rc tags.
-release = '0.1a1'
+release = '0.0.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
--
cgit v1.2.3
From 75b70b90c3235d9883a799c4aea659879b5b3d89 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sun, 24 Apr 2011 21:29:50 -0400
Subject: Fixes mdashes and other minor things.
---
docs/contributinghowto.rst | 2 +-
docs/foreward.rst | 10 +++++-----
docs/mediagoblin.rst | 21 ++++++++++++---------
3 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/docs/contributinghowto.rst b/docs/contributinghowto.rst
index a44c361f..cb5cd909 100644
--- a/docs/contributinghowto.rst
+++ b/docs/contributinghowto.rst
@@ -64,7 +64,7 @@ help with.
Are there things about our instance you want to change? Are there
things about other instances you wish were different? That's
- great--you can run your own instance!
+ great---you can run your own instance!
For more information on deploying your own instance, see
:ref:`deployment-howto`.
diff --git a/docs/foreward.rst b/docs/foreward.rst
index c1d60587..edc75e30 100644
--- a/docs/foreward.rst
+++ b/docs/foreward.rst
@@ -16,8 +16,8 @@ This manual is a living document and is in the ``mediagoblin``
repository in the ``docs/`` directory.
-Who wrote this documentation
-============================
+Who wrote this documentation?
+=============================
In no particular order:
@@ -29,10 +29,10 @@ In no particular order:
* Matt
-How should I bring up errors in the documentation
-=================================================
+I found an error in the docs---who do I tell?
+=============================================
-There are a few ways--please pick the one most convenient to you!
+There are a few ways---please pick the one most convenient to you!
1. Send an email to Will ``willg at bluesock dot org``.
2. Write up a bug report in the bug tracker at http://bugs.foocorp.net/ .
diff --git a/docs/mediagoblin.rst b/docs/mediagoblin.rst
index 6c3a8dfa..a6194dc4 100644
--- a/docs/mediagoblin.rst
+++ b/docs/mediagoblin.rst
@@ -5,12 +5,13 @@
What is GNU MediaGoblin
=======================
-Three years ago, a number of free software luminaries got together at
-the FSF office to answer the question, "What should software freedom
-look like on the participatory web?" Those thinkers included Richard
-Stallman - founder of the free software movement and instigator of the
-GNU project, Evan Prodromou - the driving force behind Status.net, a
-highly sucessful federated micro-blogging service, and FIXME.
+Three years ago (2008), a number of free software luminaries got
+together at the FSF office to answer the question, "What should
+software freedom look like on the participatory web?" Those thinkers
+included Richard Stallman---founder of the free software movement and
+instigator of the GNU project, Evan Prodromou---the driving force
+behind Status.net, a highly sucessful federated micro-blogging
+service, and FIXME.
Since that time Identi.ca and Libre.fm have answered the
freedom-loving web-user's need for micro-blogging and music sharing.
@@ -46,10 +47,12 @@ How can I participate?
See `Get Involved `.
-How is this licensed?
-=====================
+How is GNU MediaGoblin licensed?
+================================
-FIXME - write this once we work out the details
+GNU MediaGoblin software is released under an AGPLv3 license.
+
+See the ``COPYING`` file in the source for details.
Is this an official GNU Project? What does that mean?
--
cgit v1.2.3
From eb2986152aab5767ae40d1b870c7f6cb256f045d Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sun, 24 Apr 2011 21:53:57 -0400
Subject: Fixes traceback on registration
values must be unicode.
---
mediagoblin/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/models.py b/mediagoblin/models.py
index 9e0ee8ca..eef59ed4 100644
--- a/mediagoblin/models.py
+++ b/mediagoblin/models.py
@@ -49,7 +49,7 @@ class User(Document):
'created': datetime.datetime.utcnow,
'email_verified': False,
# TODO: shouldn't be active by default, must have email registration
- 'status': 'active'}
+ 'status': u'active'}
def check_login(self, password):
"""
--
cgit v1.2.3
From bb64a6073cc1ab4f2a28e3b4652ec51f3fc1d674 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 24 Apr 2011 20:55:02 -0500
Subject: Commit dummy_settings_module, of course.
---
mediagoblin/celery_setup/dummy_settings_module.py | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 mediagoblin/celery_setup/dummy_settings_module.py
diff --git a/mediagoblin/celery_setup/dummy_settings_module.py b/mediagoblin/celery_setup/dummy_settings_module.py
new file mode 100644
index 00000000..e69de29b
--
cgit v1.2.3
From 5784c4e963b12e0b866ba806f8d2e5c045780d45 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 24 Apr 2011 20:57:38 -0500
Subject: Actually call setup_celery_from_config when launching from paste.
Also changed **kw to **app_config, which is more useful of a variable
name.
---
mediagoblin/app.py | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index 78ad19a4..3ea405e9 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -22,6 +22,7 @@ from webob import Request, exc
from mediagoblin import routing, util, models, storage, staticdirect
from mediagoblin.globals import setup_globals
+from mediagoblin.celery_setup import setup_celery_from_config
class Error(Exception): pass
@@ -107,33 +108,37 @@ class MediaGoblinApp(object):
return controller(request)(environ, start_response)
-def paste_app_factory(global_config, **kw):
+def paste_app_factory(global_config, **app_config):
# Get the database connection
connection = mongokit.Connection(
- kw.get('db_host'), kw.get('db_port'))
+ app_config.get('db_host'), app_config.get('db_port'))
# Set up the storage systems.
public_store = storage.storage_system_from_paste_config(
- kw, 'publicstore')
+ app_config, 'publicstore')
queue_store = storage.storage_system_from_paste_config(
- kw, 'queuestore')
+ app_config, 'queuestore')
# Set up the staticdirect system
- if kw.has_key('direct_remote_path'):
+ if app_config.has_key('direct_remote_path'):
staticdirector = staticdirect.RemoteStaticDirect(
- kw['direct_remote_path'].strip())
- elif kw.has_key('direct_remote_paths'):
+ app_config['direct_remote_path'].strip())
+ elif app_config.has_key('direct_remote_paths'):
+ direct_remote_path_lines = app_config[
+ 'direct_remote_paths'].strip().splitlines()
staticdirector = staticdirect.MultiRemoteStaticDirect(
dict([line.strip().split(' ', 1)
- for line in kw['direct_remote_paths'].strip().splitlines()]))
+ for line in direct_remote_path_lines]))
else:
raise ImproperlyConfigured(
"One of direct_remote_path or direct_remote_paths must be provided")
+ setup_celery_from_config(app_config, global_config)
+
mgoblin_app = MediaGoblinApp(
- connection, kw.get('db_name', 'mediagoblin'),
+ connection, app_config.get('db_name', 'mediagoblin'),
public_store=public_store, queue_store=queue_store,
staticdirector=staticdirector,
- user_template_path=kw.get('local_templates'))
+ user_template_path=app_config.get('local_templates'))
return mgoblin_app
--
cgit v1.2.3
From 1bb0fdf2f4f568019c3449f269c69f406507bd7c Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Tue, 26 Apr 2011 15:46:56 -0500
Subject: HTTPFound more accurate than HTTPMovedPermanently.
(Just observed this in cc.engine, making observation here also while I'm at it :))
---
mediagoblin/app.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index 3ea405e9..59b943dd 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -82,7 +82,7 @@ class MediaGoblinApp(object):
if request.GET:
new_path_info = '%s?%s' % (
new_path_info, urllib.urlencode(request.GET))
- redirect = exc.HTTPTemporaryRedirect(location=new_path_info)
+ redirect = exc.HTTPFound(location=new_path_info)
return request.get_response(redirect)(environ, start_response)
# Okay, no matches. 404 time!
--
cgit v1.2.3
From 84489d7d4a3b3c0a897a9c4fe5176484bcf31d82 Mon Sep 17 00:00:00 2001
From: Matt Lee
Date: Wed, 27 Apr 2011 10:55:35 -0400
Subject: Updated copyright
---
docs/conf.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/conf.py b/docs/conf.py
index 6030b74d..967d84d0 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -41,7 +41,7 @@ master_doc = 'index'
# General information about the project.
project = u'GNU MediaGoblin'
-copyright = u'2011, Chris Webber, et al'
+copyright = u'2011, Free Software Foundation, Inc and contributors'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
--
cgit v1.2.3
From 9d952fdc7930dcdf1c2ee5ca6094c80a998d86ba Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Wed, 27 Apr 2011 22:42:17 -0400
Subject: Reworked contributing docs based on Asheesh's thoughts
I chatted with Asheesh on IRC today and asked him to look over the
contributer howto. He had a lot of thoughts and I factored most/all
of them in. It's much better now.
---
docs/beardomatic.rst | 2 +
docs/contributinghowto.rst | 115 ++++++++++++++++++++++++++++-----------------
docs/deploymenthowto.rst | 2 +
docs/foreward.rst | 7 +--
docs/hackinghowto.rst | 61 ++++++++++++++++++++++--
5 files changed, 139 insertions(+), 48 deletions(-)
diff --git a/docs/beardomatic.rst b/docs/beardomatic.rst
index 5ebeb239..14130f6a 100644
--- a/docs/beardomatic.rst
+++ b/docs/beardomatic.rst
@@ -1,3 +1,5 @@
+.. _beardomatic-chapter:
+
===========================================
Beardomatic: Infrastructure Documentation
===========================================
diff --git a/docs/contributinghowto.rst b/docs/contributinghowto.rst
index cb5cd909..3b3fe163 100644
--- a/docs/contributinghowto.rst
+++ b/docs/contributinghowto.rst
@@ -2,72 +2,104 @@
Contributing HOWTO
====================
-We're super glad you want to contribute!
+Join the community!
+===================
+
+We're super glad you want to join our community!
There are a variety of ways you can help us and become part of the
team. We're not just looking for coders! We're also looking for
-documentation writers, users, testers, evangelists, painters, bakers,
-candle-stick makers...
+documentation writers, users, testers, evangelists, user-interface
+designers, graphics designers, user-experience designers, system
+administrators, friends, painters, bakers, candle-stick makers...
-However, if you are a coder and you're looking to code, check out the
-:ref:`hacking-howto`.
+Here are some things you can do today:
-The rest of this chapter talks about different things we need your
-help with.
+ **Hang out with us**
-**Become a user**
+ You should hang out with us! We like people like you!
- We're building GNU MediaGoblin for us and for you but really
- you're one of us and I am you and we are we and GNU MediaGoblin is
- the walrus.
-
- Sign up for an account. Use the service. Relish in the thought
- that this service comes with a heaping side of Freedom and you can
- salt and pepper it to your liking.
+ At a bare minimum, join the `mailing list
+ `_ and say, "Hi!"
+ We also hang out on IRC in ``#mediagoblin`` on Freenode.net.
-**File bugs**
- Filing bugs is a critical part of any project. For more
- information on filing bugs, see :ref:`filing-bugs`.
+ **File bugs**
+ Filing bugs is a critical part of any project. For more
+ information on filing bugs, see :ref:`filing-bugs`.
-**Translate GNU MediaGoblin**
- Knowing more than one language is an important skill. If you are
- multi-lingual and are interested in translating GNU MediaGoblin,
- see :ref:`translating`.
+ **Write/Fix some code**
+ If you are a coder and you're looking to code, check out the
+ :ref:`hacking-howto`. We even have tips on *becoming* a coder
+ and we're willing to help you!
-**Create a theme**
- As people deploy their own GNU MediaGoblin instances, good themes
- are a must have! For more information on theming, see
- :ref:`theming-howto`.
+ **Run your own instance**
+
+ Are there things about our instance you want to change? Are
+ there things about other instances you wish were different?
+ Want to test upcoming changes? Want to create patches to
+ implement things you need? That's great---you can run your
+ own instance!
+
+ For more information on deploying your own instance, see
+ :ref:`deployment-howto`.
-**Spread the word**
+ **Spread the word**
- The seductive call of Free Software services is a powerful one,
- but many cannot hear it because it'd drowned out by the rush hour
- traffic honking of proprietary walled gardens and faux free
- services. Yuck! Be the sweet chirrup of the bird amidst the din!
- Tell others that there is a better way to live!
+ The seductive call of Free Software services is a powerful
+ one, but many cannot hear it because it'd drowned out by the
+ rush hour traffic honking of proprietary walled gardens and
+ faux free services. Yuck! Be the sweet chirrup of the bird
+ amidst the din! Tell others that there is a better way to
+ live!
- FIXME - do we want to talk about ways to spread the word?
+ FIXME - do we want to talk about ways to spread the word?
- FIXME - how can people notify us that they're spreading the word?
+ FIXME - how can people notify us that they're spreading the
+ word?
-**Run your own instance**
+We're still working on project infrastructure. We hope to have the
+bits in place for these additional things to do in the coming months:
- Are there things about our instance you want to change? Are there
- things about other instances you wish were different? That's
- great---you can run your own instance!
+ **Become a user**
+
+ We're building GNU MediaGoblin for us and for you but really
+ you're one of us and I am you and we are we and GNU
+ MediaGoblin is the walrus.
- For more information on deploying your own instance, see
- :ref:`deployment-howto`.
+ Sign up for an account. Use the service. Relish in the
+ thought that this service comes with a heaping side of Freedom
+ and you can salt and pepper it to your liking.
+
+
+ **Help other users**
+
+ Have you spent time with GNU MediaGoblin? If so, your
+ experience and wisdom are invaluable and you're the best
+ person we can think of to help other users with their
+ questions.
+
+
+ **Translate GNU MediaGoblin**
+
+ Knowing more than one language is an important skill. If you
+ are multi-lingual and are interested in translating GNU
+ MediaGoblin, see :ref:`translating`.
+
+
+ **Create a theme**
+
+ As people deploy their own GNU MediaGoblin instances, good
+ themes are a must have! For more information on theming, see
+ :ref:`theming-howto`.
Contributing thank you drawings / copyright assignment
@@ -93,8 +125,7 @@ File bugs
GNU MediaGoblin uses a bug tracker called `Redmine
`_.
-The bug tracker is at http://bugs.foocorp.net/ and bugs go in the
-``GNU mediagoblin`` project.
+The bug tracker is at ``_.
A good bug report has the following things in it:
diff --git a/docs/deploymenthowto.rst b/docs/deploymenthowto.rst
index 684ac1b1..d943e276 100644
--- a/docs/deploymenthowto.rst
+++ b/docs/deploymenthowto.rst
@@ -9,3 +9,5 @@ Step 1: Write code that can be deployed.
Step 2: ?
Step 3: Write the deployment guide and profit!
+
+But seriously, this is a stub since we're not quite there, yet.
diff --git a/docs/foreward.rst b/docs/foreward.rst
index edc75e30..d2b9c417 100644
--- a/docs/foreward.rst
+++ b/docs/foreward.rst
@@ -27,6 +27,7 @@ In no particular order:
* Greg
* Karen
* Matt
+* Asheesh
I found an error in the docs---who do I tell?
@@ -34,9 +35,9 @@ I found an error in the docs---who do I tell?
There are a few ways---please pick the one most convenient to you!
-1. Send an email to Will ``willg at bluesock dot org``.
-2. Write up a bug report in the bug tracker at http://bugs.foocorp.net/ .
-3. Tell someone on IRC ``#mediagoblin`` on Freenode.
+1. Write up a bug report in the bug tracker at http://bugs.foocorp.net/ .
+2. Tell someone on IRC ``#mediagoblin`` on Freenode.
+3. Send an email to Will ``willg at bluesock dot org``.
When you tell us about your issue, please let us know:
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 50c59d08..8b40e37d 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -8,8 +8,9 @@
So you want to hack on GNU MediaGoblin?
=======================================
-First thing to do is check out the Web site where we list all the
-project infrastructure including:
+First thing to do is check out the `Web site
+`_ where we list all the project
+infrastructure including:
* the mailing list
* the IRC channel
@@ -87,6 +88,13 @@ update your development environment. To do that, run::
Wiping your environment for a clean-slate
-----------------------------------------
+.. Note::
+
+ Unless you're doing development and working on and testing creating
+ a new instance, you will probably never have to do this. Will
+ plans to do this work and thus he documented it.
+
+
Delete the following directories:
* bin/
@@ -96,7 +104,8 @@ Delete the following directories:
* parts/
* user_dev/
-FIXME - how to drop data from mongodb?
+FIXME - how to drop data from mongodb? we should probably write a
+script.
Running the server
@@ -151,3 +160,49 @@ Bite-sized bugs to start with
=============================
FIXME - write this
+
+
+Tips for people new to coding
+=============================
+
+Python
+------
+
+GNU MediaGoblin is written using a programming language called `Python
+`_.
+
+There are two different incompatible iterations of Python which I'll
+refer to as Python 2 and Python 3. GNU MediaGoblin is written in
+Python 2 and requires Python 2.6 or 2.7. At some point, we might
+switch to Python 3, but that's a future thing.
+
+You can learn how to code in Python 2 from several excellent books
+that are freely available on the Internet:
+
+* `Learn Python the Hard Way `_
+* `Dive Into Pyton `_
+* `Python for Software Design `_
+* `A Byte of Python `_
+
+These are all excellent texts.
+
+FIXME - are there good quality Python tutorial videos?
+
+
+Libraries
+---------
+
+GNU MediaGoblin uses a variety of libraries in order to do what it
+does. These libraries are listed in the :ref:`beardomatic-chapter`
+along with links to the project Web sites and documentation for the
+libraries.
+
+There are a variety of Python-related conferences every year that have
+sessions covering many aspects of these libraries. You can find them
+at `Python Miro Community `_ [0]_.
+
+.. [0] This is a shameless plug. Will Kahn-Greene runs Python Miro
+ Community.
+
+If you have questions or need help, find us on the mailing list and on
+IRC.
--
cgit v1.2.3
From 0c953025122fbbf0fd9d6c52f490802bca3648c0 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Thu, 28 Apr 2011 10:38:37 -0400
Subject: Moves "run your own instance" to the future section
Chris correctly pointed out that you can't quite run your own instance,
yet. But that's the goal!
---
docs/contributinghowto.rst | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/docs/contributinghowto.rst b/docs/contributinghowto.rst
index 3b3fe163..ff783b9c 100644
--- a/docs/contributinghowto.rst
+++ b/docs/contributinghowto.rst
@@ -39,18 +39,6 @@ Here are some things you can do today:
and we're willing to help you!
- **Run your own instance**
-
- Are there things about our instance you want to change? Are
- there things about other instances you wish were different?
- Want to test upcoming changes? Want to create patches to
- implement things you need? That's great---you can run your
- own instance!
-
- For more information on deploying your own instance, see
- :ref:`deployment-howto`.
-
-
**Spread the word**
The seductive call of Free Software services is a powerful
@@ -88,6 +76,18 @@ bits in place for these additional things to do in the coming months:
questions.
+ **Run your own instance**
+
+ Are there things about our instance you want to change? Are
+ there things about other instances you wish were different?
+ Want to test upcoming changes? Want to create patches to
+ implement things you need? That's great---you can run your
+ own instance!
+
+ For more information on deploying your own instance, see
+ :ref:`deployment-howto`.
+
+
**Translate GNU MediaGoblin**
Knowing more than one language is an important skill. If you
--
cgit v1.2.3
From 4305e7e64bdf0889f96199a4b6219911fcb08b82 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Thu, 28 Apr 2011 10:58:16 -0400
Subject: Adds "Send encouragement" section
---
docs/contributinghowto.rst | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/docs/contributinghowto.rst b/docs/contributinghowto.rst
index ff783b9c..f10dd72a 100644
--- a/docs/contributinghowto.rst
+++ b/docs/contributinghowto.rst
@@ -39,6 +39,16 @@ Here are some things you can do today:
and we're willing to help you!
+ **Send encouragement**
+
+ A nice word from you could send someone into a tizzy of
+ productive work. Ten nice words could complete a feature.
+ One hundred nice words could get us to the next milestone.
+
+ Send it to the `mailing list `_
+ or hop into ``#mediagoblin`` on Freenode.net and let us know.
+
+
**Spread the word**
The seductive call of Free Software services is a powerful
--
cgit v1.2.3
From 515b8a48c905d28d682663aa2040850833a5d51a Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Thu, 28 Apr 2011 16:27:09 -0400
Subject: Adds placeholder file so _static exists.
---
docs/_static/placeholder | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 docs/_static/placeholder
diff --git a/docs/_static/placeholder b/docs/_static/placeholder
new file mode 100644
index 00000000..e69de29b
--
cgit v1.2.3
From 0f03e1d394273775e9cb77d6dd5fed4fe71afcf3 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sat, 30 Apr 2011 08:41:39 -0400
Subject: Adds a README
---
README | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 README
diff --git a/README b/README
new file mode 100644
index 00000000..c6e073a0
--- /dev/null
+++ b/README
@@ -0,0 +1,38 @@
+========
+ README
+========
+
+What is GNU MediaGoblin?
+========================
+
+* Initially, a place to store all your photos that’s as awesome as, if
+ not more awesome than, existing network services (Flickr, SmugMug,
+ Picasa, etc)
+* Later, a place for all sorts of media, such as video, music, etc hosting.
+* Federated with OStatus!
+* Customizable!
+* A place for people to collaborate and show off original and derived
+ creations Free, as in freedom. We’re a GNU project in the making,
+ afterall.
+
+
+Is it ready for me to use?
+==========================
+
+Not yet! We're working on it and we hope to have a usable system by
+September 2011.
+
+
+Can I help/hang out/participate/whisper sweet nothings in your ear?
+===================================================================
+
+Yes! Please join us and hang out! For more information on where we
+hang out, see `our Join page `_
+
+
+Where is the documentation?
+===========================
+
+Documentation is located in the ``docs/`` directory in a "raw"
+restructured-text form. It is also mirrored at
+http://docs.mediagoblin.org/ in HTML form.
--
cgit v1.2.3
From 87b44d61ef4c1ace855540ab35f047a2067e277c Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sat, 30 Apr 2011 08:57:08 -0400
Subject: Adds initial root page
This adds an initial root page that's ugly as sin, but makes it easier
to test what exists so far (e.g. register, login, submit pictures).
---
mediagoblin/templates/mediagoblin/root.html | 39 +++++++++++++++++++++++++++++
mediagoblin/views.py | 6 ++++-
2 files changed, 44 insertions(+), 1 deletion(-)
create mode 100644 mediagoblin/templates/mediagoblin/root.html
diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html
new file mode 100644
index 00000000..d6fffb8e
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/root.html
@@ -0,0 +1,39 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% block mediagoblin_content %}
+
+ If you don't have an account, please
+ Register.
+
+
+ {% endif %}
+{% endblock %}
diff --git a/mediagoblin/views.py b/mediagoblin/views.py
index 7a3cf098..1081ce29 100644
--- a/mediagoblin/views.py
+++ b/mediagoblin/views.py
@@ -22,7 +22,11 @@ import wtforms
from mediagoblin import models
def root_view(request):
- return Response("This is the root")
+ template = request.template_env.get_template(
+ 'mediagoblin/root.html')
+ return Response(
+ template.render(
+ {'request': request}))
class ImageSubmitForm(wtforms.Form):
--
cgit v1.2.3
From 2514dc028029e991a965aba011d9a8e65ee8ea37 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 30 Apr 2011 09:26:03 -0500
Subject: Clarified that copyright assignment is encouraged, but not mandatory.
---
docs/designdecisions.rst | 35 +++++++++++++++++++++--------------
1 file changed, 21 insertions(+), 14 deletions(-)
diff --git a/docs/designdecisions.rst b/docs/designdecisions.rst
index 3398c24b..93dffbd9 100644
--- a/docs/designdecisions.rst
+++ b/docs/designdecisions.rst
@@ -244,17 +244,24 @@ everyone is the hero by Will on "Why AGPLv3 and CC0":
.. _CC0 v1: http://creativecommons.org/publicdomain/zero/1.0/
-Why copyright assignment?
-=========================
-
-Will Kahn-Greene on "Why copyright assignment?":
-
- GNU MediaGoblin is a GNU project with the copyrights held by the
- FSF. Like other GNU projects, we require copyright assignment to
- the FSF which gives the FSF the legal ability to defend the
- AGPL-covered status of the software and distribute it.
-
- This is important to us because it guarantees that this software
- we're working so hard on will be available to everyone and will
- survive us. As long as someone is interested in using it and/or
- working on it, it will live on.
+Why (non-mandatory) copyright assignment?
+=========================================
+
+Chris Webber on "Why copyright assignment?":
+
+ GNU MediaGoblin is a GNU project with non-mandatory but heavily
+ encouraged copyright assignment to the FSF. Most, if not all, of
+ the core contributors to GNU MediaGoblin will have done a
+ copyright assignment, but unlike some other GNU projects, it isn't
+ required here. We think this is the best choice for GNU
+ MediaGoblin: it ensures that the Free Software Foundation may
+ protect the software by enforcing the AGPL if the FSF sees fit,
+ but it also means that we can immediately merge in changes from a
+ new contributor. It also means that some significant non-FSF
+ contributors might also be able to enforce the AGPL if seen fit.
+
+ Again, assignment is not mandatory, but it is heavily encouraged,
+ even incentivized: significant contributors who do a copyright
+ assignment to the FSF are eligible to have a unique goblin drawing
+ produced for them by the project's main founder, Christopher Allan
+ Webber. See :ref:`contributinghowto` for details.
--
cgit v1.2.3
From 109c87f829f2feaedac79ceaad394825e75f748c Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 30 Apr 2011 09:31:03 -0500
Subject: Changing the wording around the django-like components statement
---
docs/designdecisions.rst | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/docs/designdecisions.rst b/docs/designdecisions.rst
index 93dffbd9..8fe4d1f0 100644
--- a/docs/designdecisions.rst
+++ b/docs/designdecisions.rst
@@ -47,11 +47,10 @@ Why WSGI Minimalism
Chris Webber on "Why WSGI Minimalism":
- If you notice in the technology listI list a lot of
- components that are very `Django Project`_, but not actually
- Django components. What can I say, I really like a lot of the
- ideas in Django! Which leads to the question: why not just use
- Django?
+ If you notice in the technology list I list a lot of components
+ that are very "django-like", but not actually `Django`_
+ components. What can I say, I really like a lot of the ideas in
+ Django! Which leads to the question: why not just use Django?
While I really like Django's ideas and a lot of its components, I
also feel that most of the best ideas in Django I want have been
@@ -85,7 +84,7 @@ Chris Webber on "Why WSGI Minimalism":
deployment-howto, especially in the former making some notes on
how to make it easier for Django hackers to get started.
-.. _Django Project: http://www.djangoproject.com/
+.. _Django: http://www.djangoproject.com/
.. _Pylons: http://pylonshq.com/
.. _Pyramid: http://docs.pylonsproject.org/projects/pyramid/dev/
.. _Flask: http://flask.pocoo.org/
--
cgit v1.2.3
From 845c3ae25071dd53c5e2989f0769a5559fdce8b4 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sat, 30 Apr 2011 11:17:35 -0400
Subject: Adds section on git
* instructions for contributing patches
* learning git
* learning other utilities
---
docs/git.rst | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++
docs/hackinghowto.rst | 40 +++++++++++++++++++++++++++---
docs/index.rst | 1 +
3 files changed, 105 insertions(+), 4 deletions(-)
create mode 100644 docs/git.rst
diff --git a/docs/git.rst b/docs/git.rst
new file mode 100644
index 00000000..0db1dacf
--- /dev/null
+++ b/docs/git.rst
@@ -0,0 +1,68 @@
+==========================
+ Git, Cloning and Patches
+==========================
+
+GNU MediaGoblin uses git for all our version control and we have
+the repositories hosted on `Gitorious `_.
+
+We have two repositories. One is for the project and the other is for
+the project website.
+
+
+How to clone the project
+========================
+
+Do::
+
+ git clone git://gitorious.org/mediagoblin/mediagoblin.git
+
+
+How to send in patches
+======================
+
+All patches should be tied to issues in the `issue tracker
+`_.
+That makes it a lot easier for everyone to track proposed changes and
+make sure your hard work doesn't get dropped on the floor!
+
+If there isn't an issue for what you're working on, please create
+one. The better the description of what it is you're trying to
+fix/implement, the better everyone else is able to understand why
+you're doing what you're doing.
+
+There are two ways you could send in a patch.
+
+
+How to send in a patch from a publicly available clone
+------------------------------------------------------
+
+Add a comment to the issue you're working on with the following bits
+of information:
+
+* the url for your clone
+* the revs you want looked at
+* any details, questions, or other things that should be known
+
+
+How to send in a patch if you don't have a publicly available clone
+-------------------------------------------------------------------
+
+Assuming that the remote is our repository on gitorious and the branch
+to compare against is master, do the following:
+
+1. checkout the branch you did your work in
+2. do::
+
+ git format-patch -o patches origin/master
+
+3. either:
+
+ * tar up and attach the tarball to the issue you're working on, OR
+ * attach the patch files to the issue you're working on one at a
+ time
+
+
+How to learn git
+================
+
+Check out :ref:`hacking-howto-git`!
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 8b40e37d..1096b970 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -165,8 +165,8 @@ FIXME - write this
Tips for people new to coding
=============================
-Python
-------
+Learning Python
+---------------
GNU MediaGoblin is written using a programming language called `Python
`_.
@@ -189,8 +189,8 @@ These are all excellent texts.
FIXME - are there good quality Python tutorial videos?
-Libraries
----------
+Learning Libraries GNU MediaGoblin uses
+---------------------------------------
GNU MediaGoblin uses a variety of libraries in order to do what it
does. These libraries are listed in the :ref:`beardomatic-chapter`
@@ -206,3 +206,35 @@ at `Python Miro Community `_ [0]_.
If you have questions or need help, find us on the mailing list and on
IRC.
+
+
+.. _hacking-howto-git:
+
+Learning git
+------------
+
+git is an interesting and very powerful tool. Like all powerful
+tools, it has a learning curve.
+
+If you're new to git, we highly recommend the following resources for
+getting the hang of it:
+
+* `Learn Git `_ --- the GitHub
+ intro to git
+* `Pro Git `_ --- fantastic book
+* `Git casts `_ --- screencast covering git
+ usage
+* `Git Reference `_ --- Git reference that makes
+ it easier to get the hang of git if you're coming from other version
+ control systems
+
+
+Learning other utilities
+------------------------
+
+The `OpenHatch `_ site has a series of
+`training missions `_ which are
+designed to help you learn how to use these tools.
+
+If you're new to tar, diff and patch, we highly recommend you sign up
+with OpenHatch and do the missions.
diff --git a/docs/index.rst b/docs/index.rst
index fc8cc642..935e354b 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -17,6 +17,7 @@ Table of Contents:
deploymenthowto
hackinghowto
theminghowto
+ git
designdecisions
vision
beardomatic
--
cgit v1.2.3
From 694c235106c66ff30e52fda69f6ae229f36943b5 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 30 Apr 2011 11:32:33 -0500
Subject: Import based on the DEFAULT_SETTINGS_MODULE in
setup_celery_from_config
---
mediagoblin/celery_setup/__init__.py | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/mediagoblin/celery_setup/__init__.py b/mediagoblin/celery_setup/__init__.py
index 171b9a6f..02b451f0 100644
--- a/mediagoblin/celery_setup/__init__.py
+++ b/mediagoblin/celery_setup/__init__.py
@@ -15,6 +15,7 @@
# along with this program. If not, see .
import os
+import sys
from paste.deploy.converters import asbool, asint, aslist
@@ -69,10 +70,21 @@ def asfloat(obj):
"Bad float value: %r" % obj)
-def setup_celery_from_config(app_config, global_config):
+DEFAULT_SETTINGS_MODULE = 'mediagoblin.celery_setup.dummy_settings_module'
+
+def setup_celery_from_config(app_config, global_config,
+ settings_module=DEFAULT_SETTINGS_MODULE,
+ set_environ=True):
"""
Take a mediagoblin app config and the global config from a paste
factory and try to set up a celery settings module from this.
+
+ Args:
+ - app_config: the application config section
+ - global_config: the entire paste config, all sections
+ - settings_module: the module to populate, as a string
+ - set_environ: if set, this will CELERY_CONFIG_MODULE to the
+ settings_module
"""
if asbool(app_config.get('use_celery_environment_var')) == True:
# Don't setup celery based on our config file.
@@ -112,10 +124,11 @@ def setup_celery_from_config(app_config, global_config):
value = aslist(value)
celery_settings[key] = value
- from mediagoblin.celery_setup import dummy_settings_module
+ __import__(settings_module)
+ this_module = sys.modules[settings_module]
for key, value in celery_settings.iteritems():
- setattr(dummy_settings_module, key, value)
-
- os.environ['CELERY_CONFIG_MODULE'] = \
- 'mediagoblin.celery_setup.dummy_settings_module'
+ setattr(this_module, key, value)
+
+ if set_environ:
+ os.environ['CELERY_CONFIG_MODULE'] = settings_module
--
cgit v1.2.3
From 94459eadb8f1dae635e43c99958d37977db720c7 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sat, 30 Apr 2011 14:42:14 -0400
Subject: Changes beardomatic things to codebase things
---
docs/beardomatic.rst | 86 ----------------------------------------------------
docs/codebase.rst | 65 +++++++++++++++++++++++++++++++++++++++
docs/index.rst | 2 +-
3 files changed, 66 insertions(+), 87 deletions(-)
delete mode 100644 docs/beardomatic.rst
create mode 100644 docs/codebase.rst
diff --git a/docs/beardomatic.rst b/docs/beardomatic.rst
deleted file mode 100644
index 14130f6a..00000000
--- a/docs/beardomatic.rst
+++ /dev/null
@@ -1,86 +0,0 @@
-.. _beardomatic-chapter:
-
-===========================================
- Beardomatic: Infrastructure Documentation
-===========================================
-
-What the hell is Beardomatic?
-=============================
-
-You might be wondering, "Gah! What the hell is Beardomatic!?"
-
-Well, I'll tell you. GNU MediaGoblin is a piece of software that sits
-on a stack of libraries that do a bunch of stuff. It makes it easier
-to differentiate the bits of code that encompass GNU MediaGoblin from
-the bits of code that GNU MediaGoblin sit on top of. Thus, we came up
-with the TOTALLY AWESOME name Beardomatic.
-
-Now you might be saying, "Holy crap!? Another web framework? Are you
-going to write a mocking framework and an enumeration library, too!?"
-
-No, we're not. We're just calling this Beardomatic so that it's
-easier to talk about things. However, at some point, we can take
-these infrastructure bits from GNU MediaGoblin and turn them into a
-full-blown "web framework". We wouldn't do this to compete for
-mindshare with other web frameworks. We would do this to make it
-easier for us to bootstrap other similar projects.
-
-
-Beardomatic software stack
-==========================
-
-Beardomatic is a software stack "web framework" composed of the
-following bits:
-
-* Project infrastructure
-
- * `Python `_: the language we're using to write
- this
-
- * `Nose `_:
- for unit tests
-
- * `buildout `_: for getting dependencies,
- building a runtime environment, ...
-
-* Data storage
-
- * `MongoDB `_: the document database backend
- for storage
-
-* Web application
-
- * `Paste Deploy `_ and
- `Paste Script `_: we'll use this for
- configuring and launching the application
-
- * `WebOb `_: nice abstraction layer
- from HTTP requests, responses and WSGI bits
-
- * `Routes `_: for URL routing
-
- * `Beaker `_: for handling sessions
-
- * `Jinja2 `_: the templating engine
-
- * `MongoKit `_: the lightweight
- ORM for MongoDB we're using which will make it easier to define
- structures and all that
-
- * `WTForms `_: for handling,
- validation, and abstraction from HTML forms
-
- * `Celery `_: for task queuing (resizing
- images, encoding video, ...)
-
- * `RabbitMQ `_: for sending tasks to celery
-
-* Front end
-
- * `JQuery `_: for groovy JavaScript things
-
-
-How to ... in Beardomatic?
-==========================
-
-FIXME - write this
diff --git a/docs/codebase.rst b/docs/codebase.rst
new file mode 100644
index 00000000..2c73e7d3
--- /dev/null
+++ b/docs/codebase.rst
@@ -0,0 +1,65 @@
+.. _codebase-chapter:
+
+========================
+ Codebase Documentation
+========================
+
+This chapter covers the libraries that GNU MediaGoblin uses as well as
+various recipes for getting things done.
+
+
+Software Stack
+==============
+
+* Project infrastructure
+
+ * `Python `_: the language we're using to write
+ this
+
+ * `Nose `_:
+ for unit tests
+
+ * `buildout `_: for getting dependencies,
+ building a runtime environment, ...
+
+* Data storage
+
+ * `MongoDB `_: the document database backend
+ for storage
+
+* Web application
+
+ * `Paste Deploy `_ and
+ `Paste Script `_: we'll use this for
+ configuring and launching the application
+
+ * `WebOb `_: nice abstraction layer
+ from HTTP requests, responses and WSGI bits
+
+ * `Routes `_: for URL routing
+
+ * `Beaker `_: for handling sessions
+
+ * `Jinja2 `_: the templating engine
+
+ * `MongoKit `_: the lightweight
+ ORM for MongoDB we're using which will make it easier to define
+ structures and all that
+
+ * `WTForms `_: for handling,
+ validation, and abstraction from HTML forms
+
+ * `Celery `_: for task queuing (resizing
+ images, encoding video, ...)
+
+ * `RabbitMQ `_: for sending tasks to celery
+
+* Front end
+
+ * `JQuery `_: for groovy JavaScript things
+
+
+Recipes
+=======
+
+FIXME - write this
diff --git a/docs/index.rst b/docs/index.rst
index 935e354b..16c8ca16 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -18,9 +18,9 @@ Table of Contents:
hackinghowto
theminghowto
git
+ codebase
designdecisions
vision
- beardomatic
Indices and tables
--
cgit v1.2.3
From 1c61a6ca3b477b8eadbfc32d3c7f34f8e3531f14 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 30 Apr 2011 21:53:39 -0500
Subject: A few more corrections to make setup_celery_from_config() work right
---
mediagoblin/celery_setup/__init__.py | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/mediagoblin/celery_setup/__init__.py b/mediagoblin/celery_setup/__init__.py
index 02b451f0..143f9170 100644
--- a/mediagoblin/celery_setup/__init__.py
+++ b/mediagoblin/celery_setup/__init__.py
@@ -99,35 +99,41 @@ def setup_celery_from_config(app_config, global_config,
celery_settings = {}
# set up mongodb stuff
+ celery_settings['CELERY_RESULT_BACKEND'] = 'mongodb'
+ if not celery_settings.has_key('BROKER_BACKEND'):
+ celery_settings['BROKER_BACKEND'] = 'mongodb'
+
celery_mongo_settings = {}
+
if app_config.has_key('db_host'):
celery_mongo_settings['host'] = app_config['db_host']
- celery_settings['BROKER_HOST'] = app_config['db_host']
+ if celery_settings['BROKER_BACKEND'] == 'mongodb':
+ celery_settings['BROKER_HOST'] = app_config['db_host']
if app_config.has_key('db_port'):
celery_mongo_settings['port'] = asint(app_config['db_port'])
- celery_settings['BROKER_PORT'] = asint(app_config['db_port'])
+ if celery_settings['BROKER_BACKEND'] == 'mongodb':
+ celery_settings['BROKER_PORT'] = asint(app_config['db_port'])
celery_mongo_settings['database'] = app_config.get('db_name', 'mediagoblin')
celery_settings['CELERY_MONGODB_BACKEND_SETTINGS'] = celery_mongo_settings
- celery_settings['CELERY_RESULT_BACKEND'] = 'mongodb'
# Add anything else
for key, value in celery_conf.iteritems():
key = key.upper()
if key in KNOWN_CONFIG_BOOLS:
value = asbool(value)
- elif value in KNOWN_CONFIG_INTS:
+ elif key in KNOWN_CONFIG_INTS:
value = asint(value)
- elif value in KNOWN_CONFIG_FLOATS:
+ elif key in KNOWN_CONFIG_FLOATS:
value = asfloat(value)
- elif value in KNOWN_CONFIG_LISTS:
+ elif key in KNOWN_CONFIG_LISTS:
value = aslist(value)
celery_settings[key] = value
__import__(settings_module)
this_module = sys.modules[settings_module]
- for key, value in celery_settings.iteritems():
+ for key, value in celery_settings.items():
setattr(this_module, key, value)
if set_environ:
--
cgit v1.2.3
From ef30978ad247e00c8457c53c6aa97683a72a7777 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 30 Apr 2011 21:54:05 -0500
Subject: tests for setup_celery_from_config()
---
mediagoblin/celery_setup/__init__.py | 2 +-
mediagoblin/tests/fake_celery_module.py | 15 ++++++++++
mediagoblin/tests/test_celery_setup.py | 53 +++++++++++++++++++++++++++++++++
3 files changed, 69 insertions(+), 1 deletion(-)
create mode 100644 mediagoblin/tests/fake_celery_module.py
create mode 100644 mediagoblin/tests/test_celery_setup.py
diff --git a/mediagoblin/celery_setup/__init__.py b/mediagoblin/celery_setup/__init__.py
index 143f9170..3a7f2a5d 100644
--- a/mediagoblin/celery_setup/__init__.py
+++ b/mediagoblin/celery_setup/__init__.py
@@ -133,7 +133,7 @@ def setup_celery_from_config(app_config, global_config,
__import__(settings_module)
this_module = sys.modules[settings_module]
- for key, value in celery_settings.items():
+ for key, value in celery_settings.iteritems():
setattr(this_module, key, value)
if set_environ:
diff --git a/mediagoblin/tests/fake_celery_module.py b/mediagoblin/tests/fake_celery_module.py
new file mode 100644
index 00000000..c129cbf8
--- /dev/null
+++ b/mediagoblin/tests/fake_celery_module.py
@@ -0,0 +1,15 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
diff --git a/mediagoblin/tests/test_celery_setup.py b/mediagoblin/tests/test_celery_setup.py
new file mode 100644
index 00000000..4c2f1269
--- /dev/null
+++ b/mediagoblin/tests/test_celery_setup.py
@@ -0,0 +1,53 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import pkg_resources
+
+from mediagoblin import celery_setup
+
+
+def test_setup_celery_from_config():
+ def _wipe_testmodule_clean(module):
+ vars_to_wipe = [
+ var for var in dir(module)
+ if not var.startswith('__') and not var.endswith('__')]
+ for var in vars_to_wipe:
+ delattr(module, var)
+
+
+ celery_setup.setup_celery_from_config(
+ {},
+ {'something': {'or': 'other'},
+ 'celery': {'some_variable': 'floop',
+ 'mail_port': '2000',
+ 'CELERYD_ETA_SCHEDULER_PRECISION': '1.3',
+ 'celery_result_persistent': 'true',
+ 'celery_imports': 'foo.bar.baz this.is.an.import'}},
+ 'mediagoblin.tests.fake_celery_module', set_environ=False)
+
+ from mediagoblin.tests import fake_celery_module
+ assert fake_celery_module.SOME_VARIABLE == 'floop'
+ assert fake_celery_module.MAIL_PORT == 2000
+ assert isinstance(fake_celery_module.MAIL_PORT, int)
+ assert fake_celery_module.CELERYD_ETA_SCHEDULER_PRECISION == 1.3
+ assert isinstance(fake_celery_module.CELERYD_ETA_SCHEDULER_PRECISION, float)
+ assert fake_celery_module.CELERY_RESULT_PERSISTENT is True
+ assert fake_celery_module.CELERY_IMPORTS == [
+ 'foo.bar.baz', 'this.is.an.import']
+ assert fake_celery_module.CELERY_MONGODB_BACKEND_SETTINGS == {
+ 'database': 'mediagoblin'}
+ assert fake_celery_module.CELERY_RESULT_BACKEND == 'mongodb'
+ assert fake_celery_module.BROKER_BACKEND == 'mongodb'
--
cgit v1.2.3
From 524c8f347ff0b5c1fc176543157fa60b208906fe Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 1 May 2011 09:01:20 -0500
Subject: Second round of tests for setup_celery_from_config(), with some
database information
---
mediagoblin/tests/test_celery_setup.py | 34 +++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/tests/test_celery_setup.py b/mediagoblin/tests/test_celery_setup.py
index 4c2f1269..da18b0ef 100644
--- a/mediagoblin/tests/test_celery_setup.py
+++ b/mediagoblin/tests/test_celery_setup.py
@@ -27,7 +27,6 @@ def test_setup_celery_from_config():
for var in vars_to_wipe:
delattr(module, var)
-
celery_setup.setup_celery_from_config(
{},
{'something': {'or': 'other'},
@@ -51,3 +50,36 @@ def test_setup_celery_from_config():
'database': 'mediagoblin'}
assert fake_celery_module.CELERY_RESULT_BACKEND == 'mongodb'
assert fake_celery_module.BROKER_BACKEND == 'mongodb'
+
+ _wipe_testmodule_clean(fake_celery_module)
+
+ celery_setup.setup_celery_from_config(
+ {'db_host': 'mongodb.example.org',
+ 'db_port': '8080',
+ 'db_name': 'captain_lollerskates',
+ 'celery_section': 'vegetable'},
+ {'something': {'or': 'other'},
+ 'vegetable': {'some_variable': 'poolf',
+ 'mail_port': '2020',
+ 'CELERYD_ETA_SCHEDULER_PRECISION': '3.1',
+ 'celery_result_persistent': 'false',
+ 'celery_imports': 'baz.bar.foo import.is.a.this'}},
+ 'mediagoblin.tests.fake_celery_module', set_environ=False)
+
+ from mediagoblin.tests import fake_celery_module
+ assert fake_celery_module.SOME_VARIABLE == 'poolf'
+ assert fake_celery_module.MAIL_PORT == 2020
+ assert isinstance(fake_celery_module.MAIL_PORT, int)
+ assert fake_celery_module.CELERYD_ETA_SCHEDULER_PRECISION == 3.1
+ assert isinstance(fake_celery_module.CELERYD_ETA_SCHEDULER_PRECISION, float)
+ assert fake_celery_module.CELERY_RESULT_PERSISTENT is False
+ assert fake_celery_module.CELERY_IMPORTS == [
+ 'baz.bar.foo', 'import.is.a.this']
+ assert fake_celery_module.CELERY_MONGODB_BACKEND_SETTINGS == {
+ 'database': 'captain_lollerskates',
+ 'host': 'mongodb.example.org',
+ 'port': 8080}
+ assert fake_celery_module.CELERY_RESULT_BACKEND == 'mongodb'
+ assert fake_celery_module.BROKER_BACKEND == 'mongodb'
+ assert fake_celery_module.BROKER_HOST == 'mongodb.example.org'
+ assert fake_celery_module.BROKER_PORT == 8080
--
cgit v1.2.3
From 1e48a8308a035e78398c4982d60cfa8f947f41e3 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 1 May 2011 10:17:04 -0500
Subject: Now we have something useful: mediagoblin.celery_setup.from_celery
auto-configures a celery config module from your paste config
---
mediagoblin/celery_setup/from_celery.py | 87 +++++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)
create mode 100644 mediagoblin/celery_setup/from_celery.py
diff --git a/mediagoblin/celery_setup/from_celery.py b/mediagoblin/celery_setup/from_celery.py
new file mode 100644
index 00000000..851cbaa1
--- /dev/null
+++ b/mediagoblin/celery_setup/from_celery.py
@@ -0,0 +1,87 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import os
+
+import mongokit
+from paste.deploy.loadwsgi import NicerConfigParser
+
+from mediagoblin import storage
+from mediagoblin.celery_setup import setup_celery_from_config
+from mediagoblin.globals import setup_globals
+
+
+OUR_MODULENAME = 'mediagoblin.celery_setup.from_celery'
+
+
+def setup_self(setup_globals_func=setup_globals):
+ """
+ Transform this module into a celery config module by reading the
+ mediagoblin config file. Set the environment variable
+ MEDIAGOBLIN_CONFIG to specify where this config file is at and
+ what section it uses.
+
+ By default it defaults to 'mediagoblin.ini:app:mediagoblin'.
+
+ The first colon ":" is a delimiter between the filename and the
+ config section, so in this case the filename is 'mediagoblin.ini'
+ and the section where mediagoblin is defined is 'app:mediagoblin'.
+
+ Args:
+ - 'setup_globals_func': this is for testing purposes only. Don't
+ set this!
+ """
+ mgoblin_conf_file, mgoblin_section = os.environ.get(
+ 'MEDIAGOBLIN_CONFIG', 'mediagoblin.ini:app:mediagoblin').split(':', 1)
+ if not os.path.exists(mgoblin_conf_file):
+ raise IOError(
+ "MEDIAGOBLIN_CONFIG not set or file does not exist")
+
+ parser = NicerConfigParser(mgoblin_conf_file)
+ parser.read(mgoblin_conf_file)
+ parser._defaults.setdefault(
+ 'here', os.path.dirname(os.path.abspath(mgoblin_conf_file)))
+ parser._defaults.setdefault(
+ '__file__', os.path.abspath(mgoblin_conf_file))
+
+ mgoblin_section = dict(parser.items(mgoblin_section))
+ mgoblin_conf = dict(
+ [(section_name, dict(parser.items(section_name)))
+ for section_name in parser.sections()])
+ setup_celery_from_config(
+ mgoblin_section, mgoblin_conf,
+ settings_module=OUR_MODULENAME,
+ set_environ=False)
+
+ connection = mongokit.Connection(
+ mgoblin_section.get('db_host'), mgoblin_section.get('db_port'))
+ db = connection[mgoblin_section.get('db_name', 'mediagoblin')]
+
+ # Set up the storage systems.
+ public_store = storage.storage_system_from_paste_config(
+ mgoblin_section, 'publicstore')
+ queue_store = storage.storage_system_from_paste_config(
+ mgoblin_section, 'queuestore')
+
+ setup_globals_func(
+ db_connection=connection,
+ database=db,
+ public_store=public_store,
+ queue_store=queue_store)
+
+
+if os.environ['CELERY_CONFIG_MODULE'] == OUR_MODULENAME:
+ setup_self()
--
cgit v1.2.3
From 4a3f04323597410048b16f65dc67c8254b713140 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 1 May 2011 10:17:39 -0500
Subject: Include dependent scripts... maybe we'll change this later
---
buildout.cfg | 1 +
1 file changed, 1 insertion(+)
diff --git a/buildout.cfg b/buildout.cfg
index 2b36fb7c..520d5907 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -5,6 +5,7 @@ parts = mediagoblin make_user_dev_dirs
[mediagoblin]
recipe=zc.recipe.egg
interpreter=python
+dependent-scripts = true
eggs=mediagoblin
entry-points =
nosetests=nose:run_exit
--
cgit v1.2.3
From 132a68b54696c6a405cd9061bfe1dbe4feafb795 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 1 May 2011 18:22:27 -0500
Subject: Require sphinx & jinja2 for good measure :)
---
setup.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/setup.py b/setup.py
index 38f1a4d4..5f3ebf95 100644
--- a/setup.py
+++ b/setup.py
@@ -37,6 +37,8 @@ setup(
'nose',
'werkzeug',
'celery',
+ 'jinja2',
+ 'sphinx',
],
test_suite='nose.collector',
--
cgit v1.2.3
From 258b62c6a2046e0a378ee4da2bd2390acf535990 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 1 May 2011 19:41:22 -0500
Subject: Register the models when using from_celery
---
mediagoblin/celery_setup/from_celery.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/celery_setup/from_celery.py b/mediagoblin/celery_setup/from_celery.py
index 851cbaa1..9bd7fe07 100644
--- a/mediagoblin/celery_setup/from_celery.py
+++ b/mediagoblin/celery_setup/from_celery.py
@@ -19,7 +19,7 @@ import os
import mongokit
from paste.deploy.loadwsgi import NicerConfigParser
-from mediagoblin import storage
+from mediagoblin import storage, models
from mediagoblin.celery_setup import setup_celery_from_config
from mediagoblin.globals import setup_globals
@@ -69,6 +69,7 @@ def setup_self(setup_globals_func=setup_globals):
connection = mongokit.Connection(
mgoblin_section.get('db_host'), mgoblin_section.get('db_port'))
db = connection[mgoblin_section.get('db_name', 'mediagoblin')]
+ models.register_models(connection)
# Set up the storage systems.
public_store = storage.storage_system_from_paste_config(
--
cgit v1.2.3
From 3dca2776a63886adcaac4bde188fb9ec8e74cfe2 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Mon, 2 May 2011 12:20:53 -0400
Subject: Fixes dead references in docs.
---
docs/contributinghowto.rst | 2 ++
docs/designdecisions.rst | 2 +-
docs/hackinghowto.rst | 2 +-
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/docs/contributinghowto.rst b/docs/contributinghowto.rst
index f10dd72a..a452f2d0 100644
--- a/docs/contributinghowto.rst
+++ b/docs/contributinghowto.rst
@@ -1,3 +1,5 @@
+.. _contributing-howto-chapter:
+
====================
Contributing HOWTO
====================
diff --git a/docs/designdecisions.rst b/docs/designdecisions.rst
index 8fe4d1f0..cd902f83 100644
--- a/docs/designdecisions.rst
+++ b/docs/designdecisions.rst
@@ -263,4 +263,4 @@ Chris Webber on "Why copyright assignment?":
even incentivized: significant contributors who do a copyright
assignment to the FSF are eligible to have a unique goblin drawing
produced for them by the project's main founder, Christopher Allan
- Webber. See :ref:`contributinghowto` for details.
+ Webber. See :ref:`contributing-howto-chapter` for details.
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 1096b970..26267b7f 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -193,7 +193,7 @@ Learning Libraries GNU MediaGoblin uses
---------------------------------------
GNU MediaGoblin uses a variety of libraries in order to do what it
-does. These libraries are listed in the :ref:`beardomatic-chapter`
+does. These libraries are listed in the :ref:`codebase-chapter`
along with links to the project Web sites and documentation for the
libraries.
--
cgit v1.2.3
From 8ac897c3b6834120eeaec6e8cd1646032b1b3739 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Tue, 3 May 2011 09:49:56 -0500
Subject: Add the base.css and reference it so other people can start working
on it :)
---
mediagoblin/static/css/base.css | 1 +
mediagoblin/templates/mediagoblin/base.html | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
create mode 100644 mediagoblin/static/css/base.css
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
new file mode 100644
index 00000000..93b0b1a2
--- /dev/null
+++ b/mediagoblin/static/css/base.css
@@ -0,0 +1 @@
+/* stuff goes here :) */
\ No newline at end of file
diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html
index 01c68258..71c2e550 100644
--- a/mediagoblin/templates/mediagoblin/base.html
+++ b/mediagoblin/templates/mediagoblin/base.html
@@ -18,8 +18,8 @@
{% block title %}MediaGoblin{% endblock title %}
- {# #}
+
--
cgit v1.2.3
From 9610848c298fff67da83abd495a44be86dd4eea3 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Tue, 3 May 2011 12:07:01 -0400
Subject: Lots of documentation changes
* added a YouCanHelp directive to replace FIXMEs and encourage contributors
to help out
* moved some bits around between the hacking howto and the codebase documents
* expanded on the stub nature of the theming howto
* tweaked some other text
---
docs/codebase.rst | 61 ++++++++++++++++++++++++++++++++++++++
docs/conf.py | 4 +--
docs/contributinghowto.rst | 5 ++++
docs/hackinghowto.rst | 73 ++++++++++++++++++++++++++--------------------
docs/mediagoblin.rst | 2 +-
docs/mgext/__init__.py | 0
docs/mgext/youcanhelp.py | 44 ++++++++++++++++++++++++++++
docs/theminghowto.rst | 3 +-
8 files changed, 156 insertions(+), 36 deletions(-)
create mode 100644 docs/mgext/__init__.py
create mode 100644 docs/mgext/youcanhelp.py
diff --git a/docs/codebase.rst b/docs/codebase.rst
index 2c73e7d3..1f6ce220 100644
--- a/docs/codebase.rst
+++ b/docs/codebase.rst
@@ -7,6 +7,18 @@
This chapter covers the libraries that GNU MediaGoblin uses as well as
various recipes for getting things done.
+.. Note::
+
+ This chapter is in flux. Clearly there are things here that aren't
+ documented. If there's something you have questions about, please
+ ask!
+
+ See `the join page on the website `_
+ for where we hang out.
+
+For more information on how to get started hacking on GNU MediaGoblin,
+see :ref:`hacking-howto`.
+
Software Stack
==============
@@ -59,6 +71,55 @@ Software Stack
* `JQuery `_: for groovy JavaScript things
+
+What's where
+============
+
+After you've run buildout, you're faced with the following directory
+tree::
+
+ mediagoblin/
+ |- mediagoblin/ source code
+ | |- tests/
+ | |- templates/
+ | |- auth/
+ | \- submit/
+ |- docs/ documentation
+ |
+ | the rest of these directories are generated by
+ | buildout.
+ |
+ |- bin/ scripts
+ |- develop-eggs/
+ |- eggs/
+ |- mediagoblin.egg-info/
+ |- parts/
+ |- user_dev/ sessions, etc
+
+
+As you can see, all the code for GNU MediaGoblin is in the
+``mediagoblin`` directory.
+
+Here are some interesting files and what they do:
+
+:routing.py: maps url paths to views
+:views.py: views handle http requests
+:models.py: holds the mongodb schemas---these are the data structures
+ we're working with
+
+You'll notice that there are several sub-directories: tests,
+templates, auth, submit, ...
+
+``tests`` holds the unit test code.
+
+``templates`` holds all the templates for the output.
+
+``auth`` and ``submit`` are modules that enacpsulate authentication
+and media item submission. If you look in these directories, you'll
+see they have their own ``routing.py``, ``view.py``, and
+``models.py`` in addition to some other code.
+
+
Recipes
=======
diff --git a/docs/conf.py b/docs/conf.py
index 967d84d0..fedaf33c 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -16,7 +16,7 @@ import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
-#sys.path.insert(0, os.path.abspath('.'))
+sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
@@ -25,7 +25,7 @@ import sys, os
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = []
+extensions = ["mgext.youcanhelp"]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
diff --git a/docs/contributinghowto.rst b/docs/contributinghowto.rst
index a452f2d0..56a80b91 100644
--- a/docs/contributinghowto.rst
+++ b/docs/contributinghowto.rst
@@ -4,11 +4,16 @@
Contributing HOWTO
====================
+.. _join-the-community-section:
+
Join the community!
===================
We're super glad you want to join our community!
+See `the join page on the website `_ for
+where we hang out.
+
There are a variety of ways you can help us and become part of the
team. We're not just looking for coders! We're also looking for
documentation writers, users, testers, evangelists, user-interface
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 26267b7f..fe2411bb 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -9,16 +9,20 @@ So you want to hack on GNU MediaGoblin?
=======================================
First thing to do is check out the `Web site
-`_ where we list all the project
+`_ where we list all the project
infrastructure including:
-* the mailing list
* the IRC channel
-* the bug tracker
+* the mailing list
+* the issue tracker
Additionally, we have information on how to get involved, who to talk
to, what needs to be worked on, and other things besides!
+Second thing to do is take a look at :ref:`codebase-chapter` where
+we've started documenting how GNU MediaGoblin is built and how to add
+new things.
+
How to set up and maintain an environment for hacking
=====================================================
@@ -80,10 +84,16 @@ Updating dependencies
---------------------
While hacking on GNU MediaGoblin over time, you'll eventually have to
-update your development environment. To do that, run::
+update your development environment because the dependencies have
+changed. To do that, run::
./bin/buildout
+.. Note::
+
+ You only need to do this when dependencies are updated. You don't
+ need to do this when you've made code changes.
+
Wiping your environment for a clean-slate
-----------------------------------------
@@ -104,8 +114,12 @@ Delete the following directories:
* parts/
* user_dev/
-FIXME - how to drop data from mongodb? we should probably write a
-script.
+
+.. YouCanHelp::
+
+ If you're familiar with MongoDB and bash, we'd love to get a bash
+ script that removes all the GNU MediaGoblin data from an existing
+ MongoDB instance. Let us know!
Running the server
@@ -124,42 +138,34 @@ Run::
./bin/nosetests
-What's where
-============
+Quickstart for Django programmers
+=================================
-After you've run buildout, you're faced with the following directory
-tree::
+We're not using Django, but the codebase is very Django-like in its
+structure.
- mediagoblin/
- |- mediagoblin/ source code
- | |- tests/
- | |- templates/
- | |- auth/
- | \- submit/
- |- docs/ documentation
- |
- | the rest of these directories are generated by
- | buildout.
- |
- |- bin/ scripts
- |- develop-eggs/
- |- eggs/
- |- mediagoblin.egg-info/
- |- parts/
- |- user_dev/ sessions, etc
+* ``routing.py`` is like ``urls.py`` in Django
+* ``models.py`` has mongokit ORM definitions
+* ``views.py`` is where the views go
+We're using MongoDB. Basically, instead of a relational database with
+tables, you have a big JSON structure which acts a lot like a Python
+dict.
-Quickstart for Django programmers
-=================================
+.. YouCanHelp::
-FIXME - write this
+ If there are other things that you think would help orient someone
+ new to GNU MediaGoblin but coming from Django, let us know!
Bite-sized bugs to start with
=============================
-FIXME - write this
+**May 3rd, 2011**: We don't have a list of bite-sized bugs, yet, but
+this is important to us. If you're interested in things to work on,
+let us know on `the mailing list `_ or
+on the `IRC channel `_.
Tips for people new to coding
@@ -186,7 +192,10 @@ that are freely available on the Internet:
These are all excellent texts.
-FIXME - are there good quality Python tutorial videos?
+.. YouCanHelp::
+
+ If you know of other good quality Python tutorials and Python
+ tutorial videos, let us know!
Learning Libraries GNU MediaGoblin uses
diff --git a/docs/mediagoblin.rst b/docs/mediagoblin.rst
index a6194dc4..6d511850 100644
--- a/docs/mediagoblin.rst
+++ b/docs/mediagoblin.rst
@@ -44,7 +44,7 @@ dedicated to computer user freedom.
How can I participate?
======================
-See `Get Involved `.
+See `Get Involved `_ on the website..
How is GNU MediaGoblin licensed?
diff --git a/docs/mgext/__init__.py b/docs/mgext/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/docs/mgext/youcanhelp.py b/docs/mgext/youcanhelp.py
new file mode 100644
index 00000000..a99d0e4d
--- /dev/null
+++ b/docs/mgext/youcanhelp.py
@@ -0,0 +1,44 @@
+from docutils import nodes
+
+from sphinx.util.compat import Directive, make_admonition
+
+class youcanhelp_node(nodes.Admonition, nodes.Element):
+ pass
+
+class YouCanHelp(Directive):
+ has_content = True
+ required_arguments = 0
+ optional_arguments = 0
+ final_argument_whitespace = False
+ option_spec = {}
+
+ def run(self):
+ ad = make_admonition(
+ youcanhelp_node,
+ self.name,
+ ["You Can Help!"],
+ self.options,
+ self.content,
+ self.lineno,
+ self.content_offset,
+ self.block_text,
+ self.state,
+ self.state_machine)
+ ad[0].line = self.lineno
+ return ad
+
+def visit_youcanhelp_node(self, node):
+ self.visit_admonition(node)
+
+def depart_youcanhelp_node(self, node):
+ self.depart_admonition(node)
+
+def setup(app):
+ app.add_node(
+ youcanhelp_node,
+ html=(visit_youcanhelp_node, depart_youcanhelp_node),
+ latex=(visit_youcanhelp_node, depart_youcanhelp_node),
+ text=(visit_youcanhelp_node, depart_youcanhelp_node)
+ )
+
+ app.add_directive('youcanhelp', YouCanHelp)
diff --git a/docs/theminghowto.rst b/docs/theminghowto.rst
index 23f9cb1b..7b40685f 100644
--- a/docs/theminghowto.rst
+++ b/docs/theminghowto.rst
@@ -4,4 +4,5 @@
Theming HOWTO
===============
-FIXME - stub!
+We haven't implemented the necessary scaffolding to allow for theming
+yet. Thus, this chapter is a stub.
--
cgit v1.2.3
From db1a438f3e6f8c5c8cec20b9326a21baf4579306 Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Tue, 3 May 2011 19:49:39 +0200
Subject: Added functionality to support user email verification, email = TBD,
verification = done. Signed-off-by: Joar Wandborg
---
mediagoblin/auth/routing.py | 4 +++-
mediagoblin/auth/views.py | 23 ++++++++++++++++++
mediagoblin/models.py | 7 +++---
.../templates/mediagoblin/auth/verify_email.html | 28 ++++++++++++++++++++++
4 files changed, 58 insertions(+), 4 deletions(-)
create mode 100644 mediagoblin/templates/mediagoblin/auth/verify_email.html
diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py
index 92f19371..59762840 100644
--- a/mediagoblin/auth/routing.py
+++ b/mediagoblin/auth/routing.py
@@ -24,4 +24,6 @@ auth_routes = [
Route('mediagoblin.auth.login', '/login/',
controller='mediagoblin.auth.views:login'),
Route('mediagoblin.auth.logout', '/logout/',
- controller='mediagoblin.auth.views:logout')]
+ controller='mediagoblin.auth.views:logout'),
+ Route('mediagoblin.auth.verify_email', '/verify_email/',
+ controller='mediagoblin.auth.views:verify_email')]
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index 15e33e17..dfb6899f 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -116,3 +116,26 @@ def logout(request):
return exc.HTTPFound(
location=request.urlgen("index"))
+
+def verify_email(request):
+ import bson.objectid
+ user = request.db.User.find_one(
+ {'_id': bson.objectid.ObjectId( unicode( request.GET.get('userid') ) )})
+
+ verification_successful = bool
+
+ if user and user['verification_key'] == unicode( request.GET.get('token') ):
+ user['status'] = u'active'
+ user['email_verified'] = True
+ verification_successful = True
+ user.save()
+ else:
+ verification_successful = False
+
+ template = request.template_env.get_template(
+ 'mediagoblin/auth/verify_email.html')
+ return Response(
+ template.render(
+ {'request': request,
+ 'user': user,
+ 'verification_successful': verification_successful}))
diff --git a/mediagoblin/models.py b/mediagoblin/models.py
index eef59ed4..62cab4a5 100644
--- a/mediagoblin/models.py
+++ b/mediagoblin/models.py
@@ -14,7 +14,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-import datetime
+import datetime, uuid
from mongokit import Document, Set
@@ -41,6 +41,7 @@ class User(Document):
'pw_hash': unicode,
'email_verified': bool,
'status': unicode,
+ 'verification_key': unicode
}
required_fields = ['username', 'created', 'pw_hash', 'email']
@@ -48,8 +49,8 @@ class User(Document):
default_values = {
'created': datetime.datetime.utcnow,
'email_verified': False,
- # TODO: shouldn't be active by default, must have email registration
- 'status': u'active'}
+ 'status': u'needs_email_verification',
+ 'verification_key': unicode( uuid.uuid4() ) }
def check_login(self, password):
"""
diff --git a/mediagoblin/templates/mediagoblin/auth/verify_email.html b/mediagoblin/templates/mediagoblin/auth/verify_email.html
new file mode 100644
index 00000000..fe9094bd
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/auth/verify_email.html
@@ -0,0 +1,28 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% block mediagoblin_content %}
+
+ {% if verification_successful %}
+ Your email address has been verified!
+ {% else %}
+ The verification key or user id is incorrect
+ {% endif %}
+
+{% endblock %}
--
cgit v1.2.3
From 65f24846540052ec58174296190578a3323cac12 Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Tue, 3 May 2011 20:03:54 +0200
Subject: Added server-log.txt to .gitignore Signed-off-by: Joar Wandborg
---
.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.gitignore b/.gitignore
index b9f1554e..6f6fc624 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,4 @@ mediagoblin.egg-info
*.pyo
docs/_build/
user_dev/
+server-log.txt
\ No newline at end of file
--
cgit v1.2.3
From 41f446f4f2642e1cbcdba7e129978743ae598758 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Tue, 3 May 2011 21:45:13 -0500
Subject: Add a rudimentary media processing function.
Haven't completely checked it for workingness, and not the final form
this will take :)
---
mediagoblin/process_media/__init__.py | 50 +++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
create mode 100644 mediagoblin/process_media/__init__.py
diff --git a/mediagoblin/process_media/__init__.py b/mediagoblin/process_media/__init__.py
new file mode 100644
index 00000000..0d02a13f
--- /dev/null
+++ b/mediagoblin/process_media/__init__.py
@@ -0,0 +1,50 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import Image
+import mongokit
+from celery.task import task
+
+from mediagoblin.globals import database, queue_store, public_store
+
+
+THUMB_SIZE = 200, 200
+
+
+@task
+def process_media_initial(media_id):
+ entry = database.MediaEntry.one(
+ {'_id': mongokit.ObjectId(media_id)})
+
+ queued_filepath = entry['queue_files'].pop()
+ queued_file = queue_store.get_file(queued_filepath, 'r')
+
+ with queued_file:
+ thumb = Image(queued_file)
+ thumb.thumbnail(THUMB_SIZE, Image.ANTIALIAS)
+
+ thumb_filepath = public_store.get_unique_filepath(
+ ['media_entries',
+ unicode(entry['_id']),
+ 'thumbnail.jpg'])
+
+ with public_store.get_file(thumb_filepath, 'w') as thumb_file:
+ thumb.save(thumb_file, "JPEG")
+
+ queue_store.delete(queued_filepath)
+ entry.setdefault('media_files', []).append(thumb_filepath)
+ entry.state = 'processed'
+ entry.save()
--
cgit v1.2.3
From 883cf4973464ec19b8360d699584294446a13559 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Tue, 3 May 2011 21:45:24 -0500
Subject: Require PIL
---
setup.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/setup.py b/setup.py
index 5f3ebf95..853a5a3b 100644
--- a/setup.py
+++ b/setup.py
@@ -39,6 +39,7 @@ setup(
'celery',
'jinja2',
'sphinx',
+ 'PIL',
],
test_suite='nose.collector',
--
cgit v1.2.3
From 88816492a3776618e2a2a9ad40d49445ebba410d Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Tue, 3 May 2011 21:48:02 -0500
Subject: Force imports of stuff like mediagoblin.process_media which has tasks
we need
---
mediagoblin/celery_setup/__init__.py | 6 ++++++
mediagoblin/tests/test_celery_setup.py | 4 ++--
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/mediagoblin/celery_setup/__init__.py b/mediagoblin/celery_setup/__init__.py
index 3a7f2a5d..551b2741 100644
--- a/mediagoblin/celery_setup/__init__.py
+++ b/mediagoblin/celery_setup/__init__.py
@@ -70,6 +70,8 @@ def asfloat(obj):
"Bad float value: %r" % obj)
+MANDATORY_CELERY_IMPORTS = ['mediagoblin.process_media']
+
DEFAULT_SETTINGS_MODULE = 'mediagoblin.celery_setup.dummy_settings_module'
def setup_celery_from_config(app_config, global_config,
@@ -130,6 +132,10 @@ def setup_celery_from_config(app_config, global_config,
value = aslist(value)
celery_settings[key] = value
+ # add mandatory celery imports
+ celery_imports = celery_settings.setdefault('CELERY_IMPORTS', [])
+ celery_imports.extend(MANDATORY_CELERY_IMPORTS)
+
__import__(settings_module)
this_module = sys.modules[settings_module]
diff --git a/mediagoblin/tests/test_celery_setup.py b/mediagoblin/tests/test_celery_setup.py
index da18b0ef..558eb458 100644
--- a/mediagoblin/tests/test_celery_setup.py
+++ b/mediagoblin/tests/test_celery_setup.py
@@ -45,7 +45,7 @@ def test_setup_celery_from_config():
assert isinstance(fake_celery_module.CELERYD_ETA_SCHEDULER_PRECISION, float)
assert fake_celery_module.CELERY_RESULT_PERSISTENT is True
assert fake_celery_module.CELERY_IMPORTS == [
- 'foo.bar.baz', 'this.is.an.import']
+ 'foo.bar.baz', 'this.is.an.import', 'mediagoblin.process_media']
assert fake_celery_module.CELERY_MONGODB_BACKEND_SETTINGS == {
'database': 'mediagoblin'}
assert fake_celery_module.CELERY_RESULT_BACKEND == 'mongodb'
@@ -74,7 +74,7 @@ def test_setup_celery_from_config():
assert isinstance(fake_celery_module.CELERYD_ETA_SCHEDULER_PRECISION, float)
assert fake_celery_module.CELERY_RESULT_PERSISTENT is False
assert fake_celery_module.CELERY_IMPORTS == [
- 'baz.bar.foo', 'import.is.a.this']
+ 'baz.bar.foo', 'import.is.a.this', 'mediagoblin.process_media']
assert fake_celery_module.CELERY_MONGODB_BACKEND_SETTINGS == {
'database': 'captain_lollerskates',
'host': 'mongodb.example.org',
--
cgit v1.2.3
From 4d4f6050d84125f4fd3845e42965fd21d07a5176 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Wed, 4 May 2011 08:00:08 -0500
Subject: send_email tool and email sending tests
---
mediagoblin/tests/test_util.py | 41 ++++++++++++++++++++
mediagoblin/util.py | 87 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 128 insertions(+)
diff --git a/mediagoblin/tests/test_util.py b/mediagoblin/tests/test_util.py
index 0e7a2967..5bc31fd6 100644
--- a/mediagoblin/tests/test_util.py
+++ b/mediagoblin/tests/test_util.py
@@ -14,9 +14,14 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
+import email
+
from mediagoblin import util
+util._activate_testing()
+
+
def _import_component_testing_method(silly_string):
# Just for the sake of testing that our component importer works.
return u"'%s' is the silliest string I've ever seen" % silly_string
@@ -28,3 +33,39 @@ def test_import_component():
result = imported_func('hooobaladoobala')
expected = u"'hooobaladoobala' is the silliest string I've ever seen"
assert result == expected
+
+
+def test_send_email():
+ util._clear_test_inboxes()
+
+ # send the email
+ util.send_email(
+ "sender@mediagoblin.example.org",
+ ["amanda@example.org", "akila@example.org"],
+ "Testing is so much fun!",
+ """HAYYY GUYS!
+
+I hope you like unit tests JUST AS MUCH AS I DO!""")
+
+ # check the main inbox
+ assert len(util.EMAIL_TEST_INBOX) == 1
+ message = util.EMAIL_TEST_INBOX.pop()
+ assert message['From'] == "sender@mediagoblin.example.org"
+ assert message['To'] == "amanda@example.org, akila@example.org"
+ assert message['Subject'] == "Testing is so much fun!"
+ assert message.get_payload(decode=True) == """HAYYY GUYS!
+
+I hope you like unit tests JUST AS MUCH AS I DO!"""
+
+ # Check everything that the FakeMhost.sendmail() method got is correct
+ assert len(util.EMAIL_TEST_MBOX_INBOX) == 1
+ mbox_dict = util.EMAIL_TEST_MBOX_INBOX.pop()
+ assert mbox_dict['from'] == "sender@mediagoblin.example.org"
+ assert mbox_dict['to'] == ["amanda@example.org", "akila@example.org"]
+ mbox_message = email.message_from_string(mbox_dict['message'])
+ assert mbox_message['From'] == "sender@mediagoblin.example.org"
+ assert mbox_message['To'] == "amanda@example.org, akila@example.org"
+ assert mbox_message['Subject'] == "Testing is so much fun!"
+ assert mbox_message.get_payload(decode=True) == """HAYYY GUYS!
+
+I hope you like unit tests JUST AS MUCH AS I DO!"""
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index c9c57dfc..5b578a00 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -14,11 +14,23 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
+from email.MIMEText import MIMEText
+import smtplib
import sys
import jinja2
import mongokit
+
+TESTS_ENABLED = False
+def _activate_testing():
+ """
+ Call this to activate testing in util.py
+ """
+ global TESTS_ENABLED
+ TESTS_ENABLED = True
+
+
def get_jinja_env(user_template_path=None):
"""
Set up the Jinja environment, possibly allowing for user
@@ -72,3 +84,78 @@ def import_component(import_string):
module = sys.modules[module_name]
func = getattr(module, func_name)
return func
+
+
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+### Special email test stuff begins HERE
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+# We have two "test inboxes" here:
+#
+# EMAIL_TEST_INBOX:
+# ----------------
+# If you're writing test views, you'll probably want to check this.
+# It contains a list of MIMEText messages.
+#
+# EMAIL_TEST_MBOX_INBOX:
+# ----------------------
+# This collects the messages from the FakeMhost inbox. It's reslly
+# just here for testing the send_email method itself.
+#
+# Anyway this contains:
+# - from
+# - to: a list of email recipient addresses
+# - message: not just the body, but the whole message, including
+# headers, etc.
+#
+# ***IMPORTANT!***
+# ----------------
+# Before running tests that call functions which send email, you should
+# always call _clear_test_inboxes() to "wipe" the inboxes clean.
+
+EMAIL_TEST_INBOX = []
+EMAIL_TEST_MBOX_INBOX = []
+
+
+class FakeMhost(object):
+ """
+ Just a fake mail host so we can capture and test messages
+ from send_email
+ """
+ def connect(self):
+ pass
+
+ def sendmail(self, from_addr, to_addrs, message):
+ EMAIL_TEST_MBOX_INBOX.append(
+ {'from': from_addr,
+ 'to': to_addrs,
+ 'message': message})
+
+def _clear_test_inboxes():
+ global EMAIL_TEST_INBOX
+ global EMAIL_TEST_MBOX_INBOX
+ EMAIL_TEST_INBOX = []
+ EMAIL_TEST_MBOX_INBOX = []
+
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+###
+### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+def send_email(from_addr, to_addrs, subject, message_body):
+ # TODO: make a mock mhost if testing is enabled
+ if TESTS_ENABLED:
+ mhost = FakeMhost()
+ else:
+ mhost = smtplib.SMTP()
+
+ mhost.connect()
+
+ message = MIMEText(message_body.encode('utf-8'), 'plain', 'utf-8')
+ message['Subject'] = subject
+ message['From'] = from_addr
+ message['To'] = ', '.join(to_addrs)
+
+ if TESTS_ENABLED:
+ EMAIL_TEST_INBOX.append(message)
+
+ return mhost.sendmail(from_addr, to_addrs, message.as_string())
--
cgit v1.2.3
From 61ec968b0d1a3681bbc049d651f67100b64e1f6d Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Wed, 4 May 2011 08:11:37 -0500
Subject: A simple, maybe obvious, docstring for util.send_email()
---
mediagoblin/util.py | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index 5b578a00..d24b59b6 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -142,6 +142,16 @@ def _clear_test_inboxes():
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def send_email(from_addr, to_addrs, subject, message_body):
+ """
+ Simple email sending wrapper, use this so we can capture messages
+ for unit testing purposes.
+
+ Args:
+ - from_addr: address you're sending the email from
+ - to_addrs: list of recipient email addresses
+ - subject: subject of the email
+ - message_body: email body text
+ """
# TODO: make a mock mhost if testing is enabled
if TESTS_ENABLED:
mhost = FakeMhost()
--
cgit v1.2.3
From 1b9e2541b9e8c4449f8f78dc91c8caa7b92c7aa5 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Thu, 5 May 2011 18:22:27 -0400
Subject: Adds design decision for the name
---
docs/designdecisions.rst | 59 +++++++++++++++++++++++++++++++++++++++++++++++
docs/goblin.png | Bin 0 -> 47763 bytes
docs/snugglygoblin.png | Bin 0 -> 163754 bytes
3 files changed, 59 insertions(+)
create mode 100644 docs/goblin.png
create mode 100644 docs/snugglygoblin.png
diff --git a/docs/designdecisions.rst b/docs/designdecisions.rst
index cd902f83..50dfe3e8 100644
--- a/docs/designdecisions.rst
+++ b/docs/designdecisions.rst
@@ -7,6 +7,63 @@
This chapter talks a bit about design decisions.
+Why GNU MediaGoblin?
+====================
+
+Chris and Will on "Why GNU MediaGoblin":
+
+ Chris came up with the name MediaGoblin. The name is pretty fun.
+ It merges the idea that this is a Media hosting project with
+ Goblin which sort of sounds like gobbling. Here's a piece of
+ software that gobbles up your media for all to see.
+
+ `According to Wikipedia `_, a
+ goblin is:
+
+ a legendary evil or mischievous illiterate creature, described
+ as grotesquely evil or evil-like phantom
+
+ So are we evil? No. Are we mischievous or illiterate? Not
+ really. So what kind of goblin are we thinking about? We're
+ thinking about these goblins:
+
+ .. figure:: goblin.png
+ :alt: Cute goblin with a beret.
+
+ *Figure 1: Cute goblin with a beret. llustrated by Chris
+ Webber*
+
+ .. figure:: snugglygoblin.png
+ :scale: 50%
+ :alt: Snuggly goblin with a beret.
+
+ *Figure 2: Snuggly goblin. Illustrated by Karen Rustad*
+
+ Those are pretty cute goblins. Those are the kinds of goblins
+ we're thinking about.
+
+ Chris started doing work on the project after thinking about it
+ for a year. Then, after talking with Matt and Rob, it became an
+ official GNU project. Thus we now call it GNU MediaGoblin.
+
+ That's a lot of letters, though, so in the interest of brevity and
+ facilitating easier casual conversation and balancing that with
+ what's important to us, we have the following rules:
+
+ 1. "GNU MediaGoblin" is the name we're going to use in all official
+ capacities: web site, documentation, press releases, ...
+
+ 2. In casual conversation, it's ok to use more casual names.
+
+ 3. If you're writing about the project, we ask that you call it GNU
+ MediaGoblin.
+
+ 4. If you don't like the name, we kindly ask you to take a deep
+ breath, think a happy thought about cute little goblins playing
+ on a playground and taking cute pictures of themselves, and let
+ it go. (Will added this one.)
+
+
Why Python
==========
@@ -264,3 +321,5 @@ Chris Webber on "Why copyright assignment?":
assignment to the FSF are eligible to have a unique goblin drawing
produced for them by the project's main founder, Christopher Allan
Webber. See :ref:`contributing-howto-chapter` for details.
+
+
diff --git a/docs/goblin.png b/docs/goblin.png
new file mode 100644
index 00000000..e20265e6
Binary files /dev/null and b/docs/goblin.png differ
diff --git a/docs/snugglygoblin.png b/docs/snugglygoblin.png
new file mode 100644
index 00000000..f325ae4b
Binary files /dev/null and b/docs/snugglygoblin.png differ
--
cgit v1.2.3
From 11e5b19701a0bc7e5fd5b39c1e28d9e6b81ad4b0 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 6 May 2011 06:51:07 -0500
Subject: Moving wiping to a clean slate beneath running server/ test suite
---
docs/hackinghowto.rst | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index fe2411bb..f7e46dae 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -95,6 +95,22 @@ changed. To do that, run::
need to do this when you've made code changes.
+Running the server
+==================
+
+Run::
+
+ ./bin/paster serve mediagoblin.ini --reload
+
+
+Running the test suite
+======================
+
+Run::
+
+ ./bin/nosetests
+
+
Wiping your environment for a clean-slate
-----------------------------------------
@@ -122,22 +138,6 @@ Delete the following directories:
MongoDB instance. Let us know!
-Running the server
-==================
-
-Run::
-
- ./bin/paster serve mediagoblin.ini --reload
-
-
-Running the test suite
-======================
-
-Run::
-
- ./bin/nosetests
-
-
Quickstart for Django programmers
=================================
--
cgit v1.2.3
From 4509880386a4fc8c0d3d0e7c2176776593af8f02 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 6 May 2011 06:54:57 -0500
Subject: Made a link to the script wiping tool feature request ticket
---
docs/hackinghowto.rst | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index f7e46dae..ef49fc43 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -133,9 +133,9 @@ Delete the following directories:
.. YouCanHelp::
- If you're familiar with MongoDB and bash, we'd love to get a bash
- script that removes all the GNU MediaGoblin data from an existing
- MongoDB instance. Let us know!
+ If you're familiar with MongoDB and bash, we'd love to get a
+ `script that removes all the GNU MediaGoblin data from an existing
+ instance `_. Let us know!
Quickstart for Django programmers
--
cgit v1.2.3
From 1b734c4d67640b62d93cc41c4061555581e3f77f Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 6 May 2011 06:56:26 -0500
Subject: It doesn't necessarily have to be bash.
---
docs/hackinghowto.rst | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index ef49fc43..46353886 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -133,9 +133,9 @@ Delete the following directories:
.. YouCanHelp::
- If you're familiar with MongoDB and bash, we'd love to get a
- `script that removes all the GNU MediaGoblin data from an existing
- instance `_. Let us know!
+ If you're familiar with MongoDB, we'd love to get a `script that
+ removes all the GNU MediaGoblin data from an existing instance
+ `_. Let us know!
Quickstart for Django programmers
--
cgit v1.2.3
From 1dddd4e913b21ea9ee3bf29b32916814be563fcf Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 6 May 2011 07:44:54 -0500
Subject: A completely evil environment destroying script.
---
destroy_environment.py | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
create mode 100755 destroy_environment.py
diff --git a/destroy_environment.py b/destroy_environment.py
new file mode 100755
index 00000000..bbdeffe9
--- /dev/null
+++ b/destroy_environment.py
@@ -0,0 +1,22 @@
+#!./bin/python
+
+import pymongo
+import sys, os
+
+print "*** WARNING! ***"
+print " Running this will destroy your mediagoblin database,"
+print " remove all your media files in user_dev/, etc."
+
+drop_it = raw_input(
+ 'Are you SURE you want to destroy your environment? (if so, type "yes")> ')
+
+if not drop_it == 'yes':
+ sys.exit(1)
+
+conn = pymongo.Connection()
+conn.drop_database('mediagoblin')
+
+os.popen('rm -rf user_dev/media')
+os.popen('rm -rf user_dev/beaker')
+
+print "removed all your stuff! okay, now re-run ./bin/buildout"
--
cgit v1.2.3
From fa7f9c6184286f2b56f353b21ffaf1e1577569a3 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 6 May 2011 09:37:24 -0500
Subject: Process media! Successfully!
---
mediagoblin/models.py | 9 +++++++--
mediagoblin/process_media/__init__.py | 25 ++++++++++++++++++++-----
mediagoblin/submit/views.py | 7 +++++--
3 files changed, 32 insertions(+), 9 deletions(-)
diff --git a/mediagoblin/models.py b/mediagoblin/models.py
index eef59ed4..cd6a28cc 100644
--- a/mediagoblin/models.py
+++ b/mediagoblin/models.py
@@ -73,11 +73,16 @@ class MediaEntry(Document):
'tags': [unicode],
'state': unicode,
+ # For now let's assume there can only be one main file queued
+ # at a time
+ 'queued_media_file': [unicode],
+
+ # A dictionary of logical names to filepaths
+ 'media_files': dict,
+
# The following should be lists of lists, in appropriate file
# record form
- 'media_files': list,
'attachment_files': list,
- 'queue_files': list,
# This one should just be a single file record
'thumbnail_file': [unicode]}
diff --git a/mediagoblin/process_media/__init__.py b/mediagoblin/process_media/__init__.py
index 0d02a13f..69177fee 100644
--- a/mediagoblin/process_media/__init__.py
+++ b/mediagoblin/process_media/__init__.py
@@ -29,11 +29,11 @@ def process_media_initial(media_id):
entry = database.MediaEntry.one(
{'_id': mongokit.ObjectId(media_id)})
- queued_filepath = entry['queue_files'].pop()
+ queued_filepath = entry['queued_media_file']
queued_file = queue_store.get_file(queued_filepath, 'r')
with queued_file:
- thumb = Image(queued_file)
+ thumb = Image.open(queued_file)
thumb.thumbnail(THUMB_SIZE, Image.ANTIALIAS)
thumb_filepath = public_store.get_unique_filepath(
@@ -44,7 +44,22 @@ def process_media_initial(media_id):
with public_store.get_file(thumb_filepath, 'w') as thumb_file:
thumb.save(thumb_file, "JPEG")
- queue_store.delete(queued_filepath)
- entry.setdefault('media_files', []).append(thumb_filepath)
+ # we have to re-read because unlike PIL, not everything reads
+ # things in string representation :)
+ queued_file = queue_store.get_file(queued_filepath, 'rb')
+
+ with queued_file:
+ main_filepath = public_store.get_unique_filepath(
+ ['media_entries',
+ unicode(entry['_id']),
+ queued_filepath[-1]])
+
+ with public_store.get_file(main_filepath, 'wb') as main_file:
+ main_file.write(queued_file.read())
+
+ queue_store.delete_file(queued_filepath)
+ media_files_dict = entry.setdefault('media_files', {})
+ media_files_dict['thumb'] = thumb_filepath
+ media_files_dict['main'] = main_filepath
entry.state = 'processed'
- entry.save()
+ entry.save(validate=False)
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 926c7011..9c4eb3a4 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -22,6 +22,7 @@ from werkzeug.utils import secure_filename
from mediagoblin.decorators import require_active_login
from mediagoblin.submit import forms as submit_forms
+from mediagoblin.process_media import process_media_initial
@require_active_login
@@ -52,7 +53,6 @@ def submit_start(request):
# Now store generate the queueing related filename
queue_filepath = request.app.queue_store.get_unique_filepath(
['media_entries',
- unicode(request.user['_id']),
unicode(entry['_id']),
secure_filename(request.POST['file'].filename)])
@@ -64,9 +64,12 @@ def submit_start(request):
queue_file.write(request.POST['file'].file.read())
# Add queued filename to the entry
- entry.setdefault('queue_files', []).append(queue_filepath)
+ entry['queued_media_file'] = queue_filepath
entry.save(validate=True)
+ # queue it for processing
+ process_media_initial.delay(unicode(entry['_id']))
+
# redirect
return exc.HTTPFound(
location=request.urlgen("mediagoblin.submit.success"))
--
cgit v1.2.3
From 12b6ecac0f5188f4b4e07f9fd70e0c4a4a59a5ae Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 6 May 2011 10:01:11 -0500
Subject: Erk, we didn't save the state right before
---
mediagoblin/process_media/__init__.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mediagoblin/process_media/__init__.py b/mediagoblin/process_media/__init__.py
index 69177fee..3c4d0ca1 100644
--- a/mediagoblin/process_media/__init__.py
+++ b/mediagoblin/process_media/__init__.py
@@ -61,5 +61,5 @@ def process_media_initial(media_id):
media_files_dict = entry.setdefault('media_files', {})
media_files_dict['thumb'] = thumb_filepath
media_files_dict['main'] = main_filepath
- entry.state = 'processed'
- entry.save(validate=False)
+ entry['state'] = u'processed'
+ entry.save()
--
cgit v1.2.3
From 4c1e752a089313b11f872771f234c59d1b5b9982 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 6 May 2011 10:01:26 -0500
Subject: Actually display submitted stuff on the mainpage. Crappy, but
working!
---
mediagoblin/templates/mediagoblin/root.html | 14 ++++++++++++++
mediagoblin/views.py | 6 +++++-
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html
index d6fffb8e..06a89f3f 100644
--- a/mediagoblin/templates/mediagoblin/root.html
+++ b/mediagoblin/templates/mediagoblin/root.html
@@ -36,4 +36,18 @@
{% endif %}
+
+ {# temporarily, an "image gallery" that isn't one really ;) #}
+
+
+
+ {% for entry in media_entries %}
+
+
+
+ {% endfor %}
+
+
+
{% endblock %}
diff --git a/mediagoblin/views.py b/mediagoblin/views.py
index 1081ce29..3728d4aa 100644
--- a/mediagoblin/views.py
+++ b/mediagoblin/views.py
@@ -22,11 +22,15 @@ import wtforms
from mediagoblin import models
def root_view(request):
+ media_entries = request.db.MediaEntry.find(
+ {u'state': u'processed'})
+
template = request.template_env.get_template(
'mediagoblin/root.html')
return Response(
template.render(
- {'request': request}))
+ {'request': request,
+ 'media_entries': media_entries}))
class ImageSubmitForm(wtforms.Form):
--
cgit v1.2.3
From 1c424df505b3c9f9cceb84a4fd0ac1867b7ed9b4 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 6 May 2011 10:06:57 -0500
Subject: Instructions on running celeryd
---
docs/hackinghowto.rst | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 46353886..fdb53a25 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -103,6 +103,18 @@ Run::
./bin/paster serve mediagoblin.ini --reload
+Running celeryd
+===============
+
+You need to do this if you want your media to process and actually
+show up. It's probably a good idea in development to have the web
+server (above) running in one terminal and celeryd in another window.
+
+Run::
+
+ CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_celery ./bin/celeryd
+
+
Running the test suite
======================
--
cgit v1.2.3
From 67e63926f929cf7b6665fba00238fec227b5831e Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Sat, 7 May 2011 00:55:32 +0200
Subject: Fixed bug in models.py:User that caused all users created by the same
python process to have the same verification_key value
Signed-off-by: Joar Wandborg
---
mediagoblin/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/models.py b/mediagoblin/models.py
index 62cab4a5..c361feac 100644
--- a/mediagoblin/models.py
+++ b/mediagoblin/models.py
@@ -50,7 +50,7 @@ class User(Document):
'created': datetime.datetime.utcnow,
'email_verified': False,
'status': u'needs_email_verification',
- 'verification_key': unicode( uuid.uuid4() ) }
+ 'verification_key': uuid.uuid4 }
def check_login(self, password):
"""
--
cgit v1.2.3
From 85e1bc316ec7010d06e95b35d3496ad3ecf7ef78 Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Sat, 7 May 2011 00:57:39 +0200
Subject: mediagoblin.util.send_email now supports both list() and string() in
the 'to_addrs' parameter
Signed-off-by: Joar Wandborg
---
mediagoblin/util.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index d24b59b6..0d8bcae2 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -163,7 +163,8 @@ def send_email(from_addr, to_addrs, subject, message_body):
message = MIMEText(message_body.encode('utf-8'), 'plain', 'utf-8')
message['Subject'] = subject
message['From'] = from_addr
- message['To'] = ', '.join(to_addrs)
+ # The shorthand condition takes height for the possibility that the to_addrs argument can be either list() or string()
+ message['To'] = ', '.join(to_addrs) if type( to_addrs ) == list else to_addrs
if TESTS_ENABLED:
EMAIL_TEST_INBOX.append(message)
--
cgit v1.2.3
From b16ebe0e13247c94a3dc545761af395166956757 Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Sat, 7 May 2011 02:30:35 +0200
Subject: Changed the method used to generate uuids for verification_key, this
one works, thanks paroneayea
Signed-off-by: Joar Wandborg
---
mediagoblin/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/models.py b/mediagoblin/models.py
index c361feac..e1198187 100644
--- a/mediagoblin/models.py
+++ b/mediagoblin/models.py
@@ -50,7 +50,7 @@ class User(Document):
'created': datetime.datetime.utcnow,
'email_verified': False,
'status': u'needs_email_verification',
- 'verification_key': uuid.uuid4 }
+ 'verification_key': lambda: unicode( uuid.uuid4() ) }
def check_login(self, password):
"""
--
cgit v1.2.3
From 5c42a82c5ad4fa410219084a6f43bdc414369114 Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Sat, 7 May 2011 03:08:09 +0200
Subject: Added functionality to send out verification email upon successful
registration
Signed-off-by: Joar Wandborg
---
mediagoblin/auth/views.py | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index dfb6899f..79c09f5b 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -19,6 +19,7 @@ from webob import Response, exc
from mediagoblin.auth import lib as auth_lib
from mediagoblin.auth import forms as auth_forms
+from mediagoblin.util import send_email
def register(request):
@@ -44,9 +45,28 @@ def register(request):
entry['pw_hash'] = auth_lib.bcrypt_gen_password_hash(
request.POST['password'])
entry.save(validate=True)
-
- # TODO: Send email authentication request
-
+
+ # TODO: Move this setting to a better place
+ EMAIL_SENDER_ADDRESS = 'mediagoblin@fakehost'
+
+ ''' TODO Index - Regarding sending of verification email
+ 1. There is no error handling in place
+ 2. Due to the distributed nature of GNU MediaGoblin, we should find a way to send some additional information about the specific GNU MediaGoblin instance in the subject line. For example "GNU MediaGoblin @ Wandborg - [...]".
+ 3. The verification link generation does not detect and adapt to access via the HTTPS protocol.
+ '''
+
+ # TODO (1)
+ send_email(
+ EMAIL_SENDER_ADDRESS,
+ entry['email'],
+ 'GNU MediaGoblin - Verify email', # TODO (2)
+ 'http://{host}{uri}?userid={userid}&token={verification_key}'.format( # TODO (3)
+ host = request.host,
+ uri = request.urlgen('mediagoblin.auth.verify_email'),
+ userid = unicode( entry['_id'] ),
+ verification_key = entry['verification_key']
+ ))
+
# Redirect to register_success
return exc.HTTPFound(
location=request.urlgen("mediagoblin.auth.register_success"))
--
cgit v1.2.3
From 8842779b4e059938a0d8b94b1b3c5e3941fe8450 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Fri, 6 May 2011 21:54:10 -0400
Subject: Fixes a link in the docs
---
docs/mediagoblin.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/mediagoblin.rst b/docs/mediagoblin.rst
index 6d511850..df2190c1 100644
--- a/docs/mediagoblin.rst
+++ b/docs/mediagoblin.rst
@@ -60,7 +60,7 @@ Is this an official GNU Project? What does that mean?
We are! It means that we meet the GNU Project's rigourous standards
for free software. To find out more about what that means, check out
-`the GNU site `.
+`the GNU site `_.
Please feel free to contact us with further questions!
--
cgit v1.2.3
From 52be418afe95f7a127b12b559867921578d16dee Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Fri, 6 May 2011 22:06:36 -0400
Subject: First pass at adding virtualenv instructions.
---
docs/hackinghowto.rst | 81 +++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 75 insertions(+), 6 deletions(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index fdb53a25..40d14e24 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -49,9 +49,22 @@ requirements::
sudo apt-get install mongodb git-core python python-dev \
python-lxml
+After getting the requirements, there are two ways to build a development environment:
+
+1. Running bootstrap and buildout, OR
+2. Creating a virtual environment
+
+Pick one---don't do both!
+
+
+Creating a dev environment with bootstrap and buildout
+------------------------------------------------------
+
+.. Note::
+
+ Either follow the instructions in this section OR follow the ones
+ in the next one---don't do both!
-Running bootstrap and buildout
-------------------------------
After installing the requirements, follow these steps:
@@ -79,10 +92,6 @@ purposes this default should be fine.
`_, that should work just
fine.
-
-Updating dependencies
----------------------
-
While hacking on GNU MediaGoblin over time, you'll eventually have to
update your development environment because the dependencies have
changed. To do that, run::
@@ -95,6 +104,66 @@ changed. To do that, run::
need to do this when you've made code changes.
+Creating a dev environment with virtualenv
+------------------------------------------
+
+.. Note::
+
+ Either follow the instructions in this section OR follow the ones
+ in the previous one---don't do both!
+
+The following assumes you have these things installed:
+
+1. virtualenv:
+
+ http://pypi.python.org/pypi/virtualenv
+
+2. virtualenv wrapper:
+
+ http://www.doughellmann.com/projects/virtualenvwrapper/
+
+3. git:
+
+ http://git-scm.com/
+
+
+Follow these steps:
+
+1. Clone the repository::
+
+ git clone http://git.gitorious.org/mediagoblin/mediagoblin.git
+
+2. Create a virtual environment::
+
+ mkvirtualenv --no-site-packages mediagoblin
+
+3. If that doesn't put you in the virutal environment you just created, then do::
+
+ workon mediagoblin
+
+4. Run::
+
+ python setup.py develop
+
+
+That's it!
+
+When you want to work on GNU MediaGoblin, you need to activate the
+virtual environment like this::
+
+ workon mediagoblin
+
+If you want to deactivate it, you can do this::
+
+ deactivate
+
+.. Note::
+
+ You don't have to do anything additional to move changes you're
+ making to your virtual environment because the virtual environment
+ is pointing at the actual code files.
+
+
Running the server
==================
--
cgit v1.2.3
From 4564da2210fe42b491c74d3d32e8b5c2ddb246a8 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sat, 7 May 2011 08:49:36 -0400
Subject: Overhauls hacking howto
* reworks virtualenv section to be way better
* reworks buildout section to mirror virtualenv section
* reworks other sections that depend on which development environment
building method you chose
---
docs/hackinghowto.rst | 214 ++++++++++++++++++++++++++++++++------------------
1 file changed, 138 insertions(+), 76 deletions(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 40d14e24..a2a153aa 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -23,13 +23,21 @@ Second thing to do is take a look at :ref:`codebase-chapter` where
we've started documenting how GNU MediaGoblin is built and how to add
new things.
+Third you'll need to :ref:`get the requirements
+`.
-How to set up and maintain an environment for hacking
-=====================================================
+Fourth, you'll need to build a development environment. For this step, there are two options:
+1. :ref:`virtualenv ` OR
+2. :ref:`buildout and bootstrap `
+
+Pick one---don't do both!
+
+
+.. _get-requirements-section:
Getting requirements
---------------------
+====================
First, you need to have the following installed before you can build
an environment for hacking on GNU MediaGoblin:
@@ -49,125 +57,169 @@ requirements::
sudo apt-get install mongodb git-core python python-dev \
python-lxml
-After getting the requirements, there are two ways to build a development environment:
+.. YouCanHelp::
-1. Running bootstrap and buildout, OR
-2. Creating a virtual environment
+ If you have instructions for other GNU/Linux distributions to set
+ up requirements, let us know!
-Pick one---don't do both!
+.. _hacking-with-virtualenv:
-Creating a dev environment with bootstrap and buildout
-------------------------------------------------------
+How to set up and maintain an environment for hacking with virtualenv
+=====================================================================
.. Note::
Either follow the instructions in this section OR follow the ones
- in the next one---don't do both!
+ in :ref:`hacking-with-buildout`. But don't do both!
-After installing the requirements, follow these steps:
+**Requirements**
+
+* virtualenv: http://pypi.python.org/pypi/virtualenv
+* virtualenv wrapper: http://www.doughellmann.com/projects/virtualenvwrapper/
+* git: http://git-scm.com/
+
+
+**Create a development environment**
1. Clone the repository::
git clone http://git.gitorious.org/mediagoblin/mediagoblin.git
-2. Bootstrap and run buildout::
+2. Create a virtual environment::
- cd mediagoblin
- python bootstrap.py && ./bin/buildout
+ mkvirtualenv --no-site-packages mediagoblin
+3. If that doesn't put you in the virutal environment you just
+ created, then do::
-That's it! Using this method, buildout should create a ``user_dev``
-directory, in which certain things will be stored (media, beaker
-session stuff, etc). You can change this, but for development
-purposes this default should be fine.
+ workon mediagoblin
+4. Run::
-.. Note::
+ python setup.py develop
- We used `zc.buildout `_ because it
- involves fewer steps to get things running and less knowledge of
- Python packaging. However, if you prefer to use `virtualenv
- `_, that should work just
- fine.
+That's it!
-While hacking on GNU MediaGoblin over time, you'll eventually have to
-update your development environment because the dependencies have
-changed. To do that, run::
- ./bin/buildout
+**Activating a virtual environment**
-.. Note::
+When you want to work on GNU MediaGoblin, you need to activate the
+virtual environment like this::
+
+ workon mediagoblin
- You only need to do this when dependencies are updated. You don't
- need to do this when you've made code changes.
+**Deactivating a virtual environment**
-Creating a dev environment with virtualenv
-------------------------------------------
+If you want to deactivate it, you can do this::
-.. Note::
+ deactivate
- Either follow the instructions in this section OR follow the ones
- in the previous one---don't do both!
-The following assumes you have these things installed:
+**Updating a virtual environment with dependency changes**
-1. virtualenv:
+1. Enter the virtual environment.
- http://pypi.python.org/pypi/virtualenv
+2. Run::
-2. virtualenv wrapper:
+ python setup.py develop
- http://www.doughellmann.com/projects/virtualenvwrapper/
-3. git:
+**Updating a virtual environment with code changes**
- http://git-scm.com/
+You don't need to do anything---code changes are automatically
+available.
-Follow these steps:
+**Deleting a virtual environment**
+
+At some point you may want to delete your virtual environment.
+Perhaps it's to start over. Perhaps it's so you can test building
+development environments with virtualenv.
+
+To do this, do::
+
+ rmvirtualenv mediagoblin
+
+
+.. _hacking-with-buildout:
+
+Creating a dev environment with bootstrap and buildout
+------------------------------------------------------
+
+.. Note::
+
+ Either follow the instructions in this section OR follow the ones
+ in :ref:`hacking-with-virtualenv`. But don't do both!
+
+
+**Requirements**
+
+No additional requirements.
+
+
+**Create a development environment**
+
+After installing the requirements, follow these steps:
1. Clone the repository::
git clone http://git.gitorious.org/mediagoblin/mediagoblin.git
-2. Create a virtual environment::
+2. Bootstrap and run buildout::
- mkvirtualenv --no-site-packages mediagoblin
+ cd mediagoblin
+ python bootstrap.py && ./bin/buildout
-3. If that doesn't put you in the virutal environment you just created, then do::
- workon mediagoblin
+That's it! Using this method, buildout should create a ``user_dev``
+directory, in which certain things will be stored (media, beaker
+session stuff, etc). You can change this, but for development
+purposes this default should be fine.
-4. Run::
- python setup.py develop
+**Updating for dependency changes**
+While hacking on GNU MediaGoblin over time, you'll eventually have to
+update your development environment because the dependencies have
+changed. To do that, run::
-That's it!
+ ./bin/buildout
-When you want to work on GNU MediaGoblin, you need to activate the
-virtual environment like this::
- workon mediagoblin
+**Updating for code changes**
-If you want to deactivate it, you can do this::
+You don't need to do anything---code changes are automatically
+available.
- deactivate
-.. Note::
+**Deleting your buildout**
+
+At some point, you may want to delete your buildout. Perhaps it's to
+start over. Perhaps it's to test building development environments
+with buildout.
+
+To do this, do::
- You don't have to do anything additional to move changes you're
- making to your virtual environment because the virtual environment
- is pointing at the actual code files.
+ rm -rf bin develop-eggs eggs mediagoblin.egg-info parts user_dev
+
+
+.. _env_with_virtualenv:
+
+Creating a dev environment with virtualenv
+------------------------------------------
Running the server
==================
-Run::
+If you did virtualenv, run::
+
+ paster serve mediagoblin.ini --reload
+
+If you did buildout, run::
./bin/paster serve mediagoblin.ini --reload
@@ -179,7 +231,11 @@ You need to do this if you want your media to process and actually
show up. It's probably a good idea in development to have the web
server (above) running in one terminal and celeryd in another window.
-Run::
+If you did virtualenv, run::
+
+ CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_celery celeryd
+
+If you did buildout, run::
CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_celery ./bin/celeryd
@@ -187,30 +243,36 @@ Run::
Running the test suite
======================
-Run::
+If you did virtualenv, run::
+
+ nosetests
+
+If you did buildout, run::
./bin/nosetests
-Wiping your environment for a clean-slate
------------------------------------------
+Troubleshooting
+===============
-.. Note::
+pymongo.errors.AutoReconnect: could not find master/primary
+-----------------------------------------------------------
- Unless you're doing development and working on and testing creating
- a new instance, you will probably never have to do this. Will
- plans to do this work and thus he documented it.
+If you see this::
+ pymongo.errors.AutoReconnect: could not find master/primary
-Delete the following directories:
+then make sure mongodb is installed and running.
-* bin/
-* develop-eggs/
-* eggs/
-* mediagoblin.egg-info/
-* parts/
-* user_dev/
+Wiping your user data
+=====================
+
+.. Note::
+
+ Unless you're doing development and working on and testing creating
+ a new instance, you will probably never have to do this. Will
+ plans to do this work and thus he documented it.
.. YouCanHelp::
--
cgit v1.2.3
From 1220e775b9cea52632334e9acfde0cfac85ef25f Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sat, 7 May 2011 09:42:01 -0400
Subject: Fixes headers in hacking howto docs
---
docs/hackinghowto.rst | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index a2a153aa..7fd9b349 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -146,8 +146,8 @@ To do this, do::
.. _hacking-with-buildout:
-Creating a dev environment with bootstrap and buildout
-------------------------------------------------------
+How to set up and maintain an environment for hacking with buildout
+===================================================================
.. Note::
@@ -206,12 +206,6 @@ To do this, do::
rm -rf bin develop-eggs eggs mediagoblin.egg-info parts user_dev
-.. _env_with_virtualenv:
-
-Creating a dev environment with virtualenv
-------------------------------------------
-
-
Running the server
==================
--
cgit v1.2.3
From 7501000353ed20eda9b2b32e9a0aba63df88f1b5 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 7 May 2011 08:54:53 -0500
Subject: Be sure to read the install instructions!
---
docs/hackinghowto.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 7fd9b349..2e6d0d14 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -77,7 +77,7 @@ How to set up and maintain an environment for hacking with virtualenv
**Requirements**
* virtualenv: http://pypi.python.org/pypi/virtualenv
-* virtualenv wrapper: http://www.doughellmann.com/projects/virtualenvwrapper/
+* virtualenv wrapper: http://www.doughellmann.com/projects/virtualenvwrapper/ (be sure to read the `install instructions `_)
* git: http://git-scm.com/
--
cgit v1.2.3
From 2704f7a6cbe274b5d1969d511564f928e0ba5d29 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sat, 7 May 2011 09:56:39 -0400
Subject: Tweaks the "if mongodb isn't working" troubleshooting section
---
docs/hackinghowto.rst | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 2e6d0d14..dcade418 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -258,6 +258,12 @@ If you see this::
then make sure mongodb is installed and running.
+If it's installed, check the mongodb log. On my machine, that's ``/var/log/mongodb/mongodb.log``. If you see something like::
+
+ old lock file: /var/lib/mongodb/mongod.lock. probably means...
+
+Then delete the lock file and relaunch mongodb.
+
Wiping your user data
=====================
--
cgit v1.2.3
From 2bae877e6769842900694f49a5e27c1bc31507e0 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sat, 7 May 2011 09:57:37 -0400
Subject: Wraps the virtualenv wrapper line
---
docs/hackinghowto.rst | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index dcade418..d3784820 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -77,7 +77,10 @@ How to set up and maintain an environment for hacking with virtualenv
**Requirements**
* virtualenv: http://pypi.python.org/pypi/virtualenv
-* virtualenv wrapper: http://www.doughellmann.com/projects/virtualenvwrapper/ (be sure to read the `install instructions `_)
+* virtualenv wrapper:
+ http://www.doughellmann.com/projects/virtualenvwrapper/ (be sure to
+ read the `install instructions
+ `_)
* git: http://git-scm.com/
--
cgit v1.2.3
From 27057b42fb68e3f640a1788d6de36649af6455f7 Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Sat, 7 May 2011 09:57:58 -0400
Subject: Removes the git requirement--that's redundant
---
docs/hackinghowto.rst | 1 -
1 file changed, 1 deletion(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index d3784820..73522ec6 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -81,7 +81,6 @@ How to set up and maintain an environment for hacking with virtualenv
http://www.doughellmann.com/projects/virtualenvwrapper/ (be sure to
read the `install instructions
`_)
-* git: http://git-scm.com/
**Create a development environment**
--
cgit v1.2.3
From 7a5ddb45dcf55c6d651b4a32dc1924e54b77c0f0 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 7 May 2011 13:58:36 -0500
Subject: Reversing buildout and virtualenv instructions because I think
virtualenv is easier if you don't know how this stuff works, and it works.
---
docs/hackinghowto.rst | 132 ++++++++++++++++++++++++++------------------------
1 file changed, 68 insertions(+), 64 deletions(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 73522ec6..d829b1c0 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -28,8 +28,8 @@ Third you'll need to :ref:`get the requirements
Fourth, you'll need to build a development environment. For this step, there are two options:
-1. :ref:`virtualenv ` OR
-2. :ref:`buildout and bootstrap `
+1. :ref:`buildout and bootstrap ` (easier) OR
+2. :ref:`virtualenv ` (more flexible, but harder)
Pick one---don't do both!
@@ -63,6 +63,72 @@ requirements::
up requirements, let us know!
+.. _hacking-with-buildout:
+
+How to set up and maintain an environment for hacking with buildout
+===================================================================
+
+.. Note::
+
+ Either follow the instructions in this section OR follow the ones
+ in :ref:`hacking-with-virtualenv`. But don't do both!
+
+
+**Requirements**
+
+No additional requirements.
+
+
+**Create a development environment**
+
+After installing the requirements, follow these steps:
+
+1. Clone the repository::
+
+ git clone http://git.gitorious.org/mediagoblin/mediagoblin.git
+
+2. Bootstrap and run buildout::
+
+ cd mediagoblin
+ python bootstrap.py && ./bin/buildout
+
+
+That's it! Using this method, buildout should create a ``user_dev``
+directory, in which certain things will be stored (media, beaker
+session stuff, etc). You can change this, but for development
+purposes this default should be fine.
+
+
+**Updating for dependency changes**
+
+While hacking on GNU MediaGoblin over time, you'll eventually have to
+update your development environment because the dependencies have
+changed. To do that, run::
+
+ ./bin/buildout
+
+
+**Updating for code changes**
+
+You don't need to do anything---code changes are automatically
+available.
+
+
+**Deleting your buildout**
+
+At some point, you may want to delete your buildout. Perhaps it's to
+start over. Perhaps it's to test building development environments
+with buildout.
+
+To do this, do::
+
+ rm -rf bin develop-eggs eggs mediagoblin.egg-info parts user_dev
+
+Usually buildout works pretty great and is super easy, but if you get
+problems with python-dateutil conflicts on your system, you may need
+to use virtualenv instead.
+
+
.. _hacking-with-virtualenv:
How to set up and maintain an environment for hacking with virtualenv
@@ -146,68 +212,6 @@ To do this, do::
rmvirtualenv mediagoblin
-.. _hacking-with-buildout:
-
-How to set up and maintain an environment for hacking with buildout
-===================================================================
-
-.. Note::
-
- Either follow the instructions in this section OR follow the ones
- in :ref:`hacking-with-virtualenv`. But don't do both!
-
-
-**Requirements**
-
-No additional requirements.
-
-
-**Create a development environment**
-
-After installing the requirements, follow these steps:
-
-1. Clone the repository::
-
- git clone http://git.gitorious.org/mediagoblin/mediagoblin.git
-
-2. Bootstrap and run buildout::
-
- cd mediagoblin
- python bootstrap.py && ./bin/buildout
-
-
-That's it! Using this method, buildout should create a ``user_dev``
-directory, in which certain things will be stored (media, beaker
-session stuff, etc). You can change this, but for development
-purposes this default should be fine.
-
-
-**Updating for dependency changes**
-
-While hacking on GNU MediaGoblin over time, you'll eventually have to
-update your development environment because the dependencies have
-changed. To do that, run::
-
- ./bin/buildout
-
-
-**Updating for code changes**
-
-You don't need to do anything---code changes are automatically
-available.
-
-
-**Deleting your buildout**
-
-At some point, you may want to delete your buildout. Perhaps it's to
-start over. Perhaps it's to test building development environments
-with buildout.
-
-To do this, do::
-
- rm -rf bin develop-eggs eggs mediagoblin.egg-info parts user_dev
-
-
Running the server
==================
--
cgit v1.2.3
From 4c093e85c7457e989b22b5274f240e3ccfdab210 Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Sun, 8 May 2011 00:55:57 +0200
Subject: Made changes according to http://bugs.foocorp.net/issues/271#note-7
Signed-off-by: Joar Wandborg
---
mediagoblin.ini | 1 +
mediagoblin/app.py | 4 ++
mediagoblin/auth/views.py | 48 +++++++++++++---------
mediagoblin/celery_setup/from_celery.py | 4 ++
.../templates/mediagoblin/auth/verify_email.html | 4 +-
mediagoblin/util.py | 3 +-
6 files changed, 41 insertions(+), 23 deletions(-)
diff --git a/mediagoblin.ini b/mediagoblin.ini
index c6dd4f76..a54eebd5 100644
--- a/mediagoblin.ini
+++ b/mediagoblin.ini
@@ -14,6 +14,7 @@ queuestore_base_dir = %(here)s/user_dev/media/queue
publicstore_base_dir = %(here)s/user_dev/media/public
publicstore_base_url = /mgoblin_media/
direct_remote_path = /mgoblin_static/
+email_sender_address = "notice@mediagoblin.org"
## Uncomment this to put some user-overriding templates here
#local_templates = %(here)s/user_dev/templates/
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index 59b943dd..ca3de6ca 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -36,6 +36,7 @@ class MediaGoblinApp(object):
def __init__(self, connection, database_path,
public_store, queue_store,
staticdirector,
+ email_sender_address,
user_template_path=None):
# Get the template environment
self.template_env = util.get_jinja_env(user_template_path)
@@ -59,6 +60,7 @@ class MediaGoblinApp(object):
# validators, etc, which might not access to the request
# object.
setup_globals(
+ email_sender_address=email_sender_address,
db_connection=connection,
database=self.db,
public_store=self.public_store,
@@ -139,6 +141,8 @@ def paste_app_factory(global_config, **app_config):
connection, app_config.get('db_name', 'mediagoblin'),
public_store=public_store, queue_store=queue_store,
staticdirector=staticdirector,
+ email_sender_address=app_config.get('email_sender_address',
+ 'notice@medigoblin.org'),
user_template_path=app_config.get('local_templates'))
return mgoblin_app
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index 79c09f5b..7468def0 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -20,6 +20,7 @@ from webob import Response, exc
from mediagoblin.auth import lib as auth_lib
from mediagoblin.auth import forms as auth_forms
from mediagoblin.util import send_email
+from mediagoblin import globals as mgoblin_globals
def register(request):
@@ -49,23 +50,26 @@ def register(request):
# TODO: Move this setting to a better place
EMAIL_SENDER_ADDRESS = 'mediagoblin@fakehost'
- ''' TODO Index - Regarding sending of verification email
- 1. There is no error handling in place
- 2. Due to the distributed nature of GNU MediaGoblin, we should find a way to send some additional information about the specific GNU MediaGoblin instance in the subject line. For example "GNU MediaGoblin @ Wandborg - [...]".
- 3. The verification link generation does not detect and adapt to access via the HTTPS protocol.
- '''
-
- # TODO (1)
- send_email(
- EMAIL_SENDER_ADDRESS,
- entry['email'],
- 'GNU MediaGoblin - Verify email', # TODO (2)
- 'http://{host}{uri}?userid={userid}&token={verification_key}'.format( # TODO (3)
- host = request.host,
- uri = request.urlgen('mediagoblin.auth.verify_email'),
- userid = unicode( entry['_id'] ),
- verification_key = entry['verification_key']
- ))
+ email_template = request.template_env.get_template(
+ 'mediagoblin/auth/verification_email.txt')
+
+ # TODO: There is no error handling in place
+ send_email(
+ mgoblin_globals.email_sender_address,
+ list(entry['email']),
+ # TODO
+ # Due to the distributed nature of GNU MediaGoblin, we should
+ # find a way to send some additional information about the
+ # specific GNU MediaGoblin instance in the subject line. For
+ # example "GNU MediaGoblin @ Wandborg - [...]".
+ 'GNU MediaGoblin - Verify email',
+ email_template.render(
+ username=entry['username'],
+ verification_url='http://{host}{uri}?userid={userid}&token={verification_key}'.format(
+ host=request.host,
+ uri=request.urlgen('mediagoblin.auth.verify_email'),
+ userid=unicode(entry['_id']),
+ verification_key=entry['verification_key'])))
# Redirect to register_success
return exc.HTTPFound(
@@ -138,13 +142,19 @@ def logout(request):
location=request.urlgen("index"))
def verify_email(request):
+ """
+ Email verification view
+
+ validates GET parameters against database and unlocks the user account, if
+ you are lucky :)
+ """
import bson.objectid
user = request.db.User.find_one(
- {'_id': bson.objectid.ObjectId( unicode( request.GET.get('userid') ) )})
+ {'_id': bson.objectid.ObjectId(unicode(request.GET.get('userid')))})
verification_successful = bool
- if user and user['verification_key'] == unicode( request.GET.get('token') ):
+ if user and user['verification_key'] == unicode(request.GET.get('token')):
user['status'] = u'active'
user['email_verified'] = True
verification_successful = True
diff --git a/mediagoblin/celery_setup/from_celery.py b/mediagoblin/celery_setup/from_celery.py
index 9bd7fe07..387538e6 100644
--- a/mediagoblin/celery_setup/from_celery.py
+++ b/mediagoblin/celery_setup/from_celery.py
@@ -22,6 +22,7 @@ from paste.deploy.loadwsgi import NicerConfigParser
from mediagoblin import storage, models
from mediagoblin.celery_setup import setup_celery_from_config
from mediagoblin.globals import setup_globals
+from mediagoblin import globals as mgoblin_globals
OUR_MODULENAME = 'mediagoblin.celery_setup.from_celery'
@@ -81,6 +82,9 @@ def setup_self(setup_globals_func=setup_globals):
db_connection=connection,
database=db,
public_store=public_store,
+ email_sender_address=mgoblin_section.get(
+ 'email_sender_address',
+ 'notice@mediagoblin.org'),
queue_store=queue_store)
diff --git a/mediagoblin/templates/mediagoblin/auth/verify_email.html b/mediagoblin/templates/mediagoblin/auth/verify_email.html
index fe9094bd..b6e6d1f8 100644
--- a/mediagoblin/templates/mediagoblin/auth/verify_email.html
+++ b/mediagoblin/templates/mediagoblin/auth/verify_email.html
@@ -20,9 +20,9 @@
{% block mediagoblin_content %}
{% if verification_successful %}
- Your email address has been verified!
+ Your email address has been verified!
{% else %}
- The verification key or user id is incorrect
+ The verification key or user id is incorrect
{% endif %}
{% endblock %}
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index 0d8bcae2..d24b59b6 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -163,8 +163,7 @@ def send_email(from_addr, to_addrs, subject, message_body):
message = MIMEText(message_body.encode('utf-8'), 'plain', 'utf-8')
message['Subject'] = subject
message['From'] = from_addr
- # The shorthand condition takes height for the possibility that the to_addrs argument can be either list() or string()
- message['To'] = ', '.join(to_addrs) if type( to_addrs ) == list else to_addrs
+ message['To'] = ', '.join(to_addrs)
if TESTS_ENABLED:
EMAIL_TEST_INBOX.append(message)
--
cgit v1.2.3
From 4942b63711e53162a0ae5e7e5fdfd902df4e5e66 Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Sun, 8 May 2011 01:58:58 +0200
Subject: Removed unused variable
Signed-off-by: Joar Wandborg
---
mediagoblin/auth/views.py | 3 ---
1 file changed, 3 deletions(-)
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index 7468def0..3ef1e75f 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -47,9 +47,6 @@ def register(request):
request.POST['password'])
entry.save(validate=True)
- # TODO: Move this setting to a better place
- EMAIL_SENDER_ADDRESS = 'mediagoblin@fakehost'
-
email_template = request.template_env.get_template(
'mediagoblin/auth/verification_email.txt')
--
cgit v1.2.3
From 07a3a69cd476ac8844f96d5edb916d652bb91e42 Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Sun, 8 May 2011 02:01:26 +0200
Subject: Added verification email template
Signed-off-by: Joar Wandborg
---
.../mediagoblin/auth/verification_email.txt | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
create mode 100644 mediagoblin/templates/mediagoblin/auth/verification_email.txt
diff --git a/mediagoblin/templates/mediagoblin/auth/verification_email.txt b/mediagoblin/templates/mediagoblin/auth/verification_email.txt
new file mode 100644
index 00000000..ce0629eb
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/auth/verification_email.txt
@@ -0,0 +1,22 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+Hi {{ username }},
+
+to activate your GNU MediaGoblin account, open the following URL in your web browser
+
+{{ verification_url }}
--
cgit v1.2.3
From 8a6a81bcaa557f1d7ceebea8b372be7cc3423ca2 Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Sun, 8 May 2011 02:03:11 +0200
Subject: Updated default sender address
Signed-off-by: Joar Wandborg
---
mediagoblin.ini | 2 +-
mediagoblin/app.py | 2 +-
mediagoblin/celery_setup/from_celery.py | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/mediagoblin.ini b/mediagoblin.ini
index a54eebd5..951971a9 100644
--- a/mediagoblin.ini
+++ b/mediagoblin.ini
@@ -14,7 +14,7 @@ queuestore_base_dir = %(here)s/user_dev/media/queue
publicstore_base_dir = %(here)s/user_dev/media/public
publicstore_base_url = /mgoblin_media/
direct_remote_path = /mgoblin_static/
-email_sender_address = "notice@mediagoblin.org"
+email_sender_address = "notice@mediagoblin.example.org"
## Uncomment this to put some user-overriding templates here
#local_templates = %(here)s/user_dev/templates/
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index ca3de6ca..ad9e77df 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -142,7 +142,7 @@ def paste_app_factory(global_config, **app_config):
public_store=public_store, queue_store=queue_store,
staticdirector=staticdirector,
email_sender_address=app_config.get('email_sender_address',
- 'notice@medigoblin.org'),
+ 'notice@mediagoblin.example.org'),
user_template_path=app_config.get('local_templates'))
return mgoblin_app
diff --git a/mediagoblin/celery_setup/from_celery.py b/mediagoblin/celery_setup/from_celery.py
index 387538e6..218ebfeb 100644
--- a/mediagoblin/celery_setup/from_celery.py
+++ b/mediagoblin/celery_setup/from_celery.py
@@ -84,7 +84,7 @@ def setup_self(setup_globals_func=setup_globals):
public_store=public_store,
email_sender_address=mgoblin_section.get(
'email_sender_address',
- 'notice@mediagoblin.org'),
+ 'notice@mediagoblin.example.org'),
queue_store=queue_store)
--
cgit v1.2.3
From 3eae207c54b6c8fa4c2e122403b4462d93b8b713 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 7 May 2011 22:44:37 -0500
Subject: [to_email] rather than list(to_email) which makes a nasty series like
['e','m','a','i','l']
---
mediagoblin/auth/views.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index 3ef1e75f..c3d24c74 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -53,7 +53,7 @@ def register(request):
# TODO: There is no error handling in place
send_email(
mgoblin_globals.email_sender_address,
- list(entry['email']),
+ [entry['email']],
# TODO
# Due to the distributed nature of GNU MediaGoblin, we should
# find a way to send some additional information about the
--
cgit v1.2.3
From 29f3fb7052a0a512d5970a936b30175b9c7eef63 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 7 May 2011 22:45:06 -0500
Subject: Added an email debug mode which, by default, is enabled
---
mediagoblin.ini | 2 ++
mediagoblin/app.py | 9 ++++++---
mediagoblin/celery_setup/from_celery.py | 1 +
mediagoblin/util.py | 17 ++++++++++++++---
4 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/mediagoblin.ini b/mediagoblin.ini
index 951971a9..b85f22ea 100644
--- a/mediagoblin.ini
+++ b/mediagoblin.ini
@@ -15,6 +15,8 @@ publicstore_base_dir = %(here)s/user_dev/media/public
publicstore_base_url = /mgoblin_media/
direct_remote_path = /mgoblin_static/
email_sender_address = "notice@mediagoblin.example.org"
+# set to false to enable sending notices
+email_debug_mode = true
## Uncomment this to put some user-overriding templates here
#local_templates = %(here)s/user_dev/templates/
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index ad9e77df..e93e0c4e 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -18,6 +18,7 @@ import urllib
import routes
import mongokit
+from paste.deploy.converters import asbool
from webob import Request, exc
from mediagoblin import routing, util, models, storage, staticdirect
@@ -36,7 +37,7 @@ class MediaGoblinApp(object):
def __init__(self, connection, database_path,
public_store, queue_store,
staticdirector,
- email_sender_address,
+ email_sender_address, email_debug_mode,
user_template_path=None):
# Get the template environment
self.template_env = util.get_jinja_env(user_template_path)
@@ -61,6 +62,7 @@ class MediaGoblinApp(object):
# object.
setup_globals(
email_sender_address=email_sender_address,
+ email_debug_mode=email_debug_mode,
db_connection=connection,
database=self.db,
public_store=self.public_store,
@@ -141,8 +143,9 @@ def paste_app_factory(global_config, **app_config):
connection, app_config.get('db_name', 'mediagoblin'),
public_store=public_store, queue_store=queue_store,
staticdirector=staticdirector,
- email_sender_address=app_config.get('email_sender_address',
- 'notice@mediagoblin.example.org'),
+ email_sender_address=app_config.get(
+ 'email_sender_address', 'notice@mediagoblin.example.org'),
+ email_debug_mode=app_config.get('email_debug_mode'),
user_template_path=app_config.get('local_templates'))
return mgoblin_app
diff --git a/mediagoblin/celery_setup/from_celery.py b/mediagoblin/celery_setup/from_celery.py
index 218ebfeb..4ad2c1d1 100644
--- a/mediagoblin/celery_setup/from_celery.py
+++ b/mediagoblin/celery_setup/from_celery.py
@@ -82,6 +82,7 @@ def setup_self(setup_globals_func=setup_globals):
db_connection=connection,
database=db,
public_store=public_store,
+ email_debug_mode=app_config.get('email_debug_mode'),
email_sender_address=mgoblin_section.get(
'email_sender_address',
'notice@mediagoblin.example.org'),
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index d24b59b6..8695180a 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -21,6 +21,8 @@ import sys
import jinja2
import mongokit
+from mediagoblin import globals as mgoblin_globals
+
TESTS_ENABLED = False
def _activate_testing():
@@ -153,9 +155,9 @@ def send_email(from_addr, to_addrs, subject, message_body):
- message_body: email body text
"""
# TODO: make a mock mhost if testing is enabled
- if TESTS_ENABLED:
+ if TESTS_ENABLED or mgoblin_globals.email_debug_mode:
mhost = FakeMhost()
- else:
+ elif not mgoblin_globals.email_debug_mode:
mhost = smtplib.SMTP()
mhost.connect()
@@ -168,4 +170,13 @@ def send_email(from_addr, to_addrs, subject, message_body):
if TESTS_ENABLED:
EMAIL_TEST_INBOX.append(message)
- return mhost.sendmail(from_addr, to_addrs, message.as_string())
+ elif mgoblin_globals.email_debug_mode:
+ print u"===== Email ====="
+ print u"From address: %s" % message['From']
+ print u"To addresses: %s" % message['To']
+ print u"Subject: %s" % message['Subject']
+ print u"-- Body: --"
+ print message.get_payload(decode=True)
+
+ else:
+ return mhost.sendmail(from_addr, to_addrs, message.as_string())
--
cgit v1.2.3
From a5b06bb0750afd9d2751f92230d4dcb5c76d61c5 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 7 May 2011 22:45:30 -0500
Subject: Removing unused sys import from setup.py
---
setup.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/setup.py b/setup.py
index 853a5a3b..7b483a57 100644
--- a/setup.py
+++ b/setup.py
@@ -16,8 +16,6 @@
from setuptools import setup, find_packages
-import sys
-
setup(
name = "mediagoblin",
version = "0.0.1",
--
cgit v1.2.3
From 19f8a24e4187b81f18a0def87b2b170a40977ff1 Mon Sep 17 00:00:00 2001
From: Sebastian Spaeth
Date: Sun, 8 May 2011 11:12:38 +0200
Subject: app.py: Need to pass in port number as 'int'
When we configured an explicite db_port in mediagoblin.ini, paster would
crash claiming that the port number must be an int. Given that we don't
have a "get_conf_int()" function or something similar (yet?), simply
convert the port number to int before passing it to the mongo Connection
instance.
Signed-off-by: Sebastian Spaeth
---
mediagoblin/app.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index e93e0c4e..5c094f38 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -114,8 +114,9 @@ class MediaGoblinApp(object):
def paste_app_factory(global_config, **app_config):
# Get the database connection
+ port = int(app_config.get('db_port'))
connection = mongokit.Connection(
- app_config.get('db_host'), app_config.get('db_port'))
+ app_config.get('db_host'), port)
# Set up the storage systems.
public_store = storage.storage_system_from_paste_config(
--
cgit v1.2.3
From eef100ada52adc4c1f65c7a006b92685f7317ee5 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 8 May 2011 07:07:08 -0500
Subject: mgoblin_section.get, not app_config.get (doh)
My name's Chris Webber and I ignore pyflakes warnings.
---
mediagoblin/celery_setup/from_celery.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/celery_setup/from_celery.py b/mediagoblin/celery_setup/from_celery.py
index 4ad2c1d1..0ddfcc76 100644
--- a/mediagoblin/celery_setup/from_celery.py
+++ b/mediagoblin/celery_setup/from_celery.py
@@ -82,7 +82,7 @@ def setup_self(setup_globals_func=setup_globals):
db_connection=connection,
database=db,
public_store=public_store,
- email_debug_mode=app_config.get('email_debug_mode'),
+ email_debug_mode=mgoblin_section.get('email_debug_mode'),
email_sender_address=mgoblin_section.get(
'email_sender_address',
'notice@mediagoblin.example.org'),
--
cgit v1.2.3
From a1eb1f6051300e5d3ce9d1f32d28a25a567e73d8 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 8 May 2011 07:16:50 -0500
Subject: Only convert db port if it's there and use asint to do it (better
errors if failing)
---
mediagoblin/app.py | 6 ++++--
mediagoblin/celery_setup/from_celery.py | 6 +++++-
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index 5c094f38..913e530e 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -18,7 +18,7 @@ import urllib
import routes
import mongokit
-from paste.deploy.converters import asbool
+from paste.deploy.converters import asint
from webob import Request, exc
from mediagoblin import routing, util, models, storage, staticdirect
@@ -114,7 +114,9 @@ class MediaGoblinApp(object):
def paste_app_factory(global_config, **app_config):
# Get the database connection
- port = int(app_config.get('db_port'))
+ port = app_config.get('db_port')
+ if port:
+ port = asint(port)
connection = mongokit.Connection(
app_config.get('db_host'), port)
diff --git a/mediagoblin/celery_setup/from_celery.py b/mediagoblin/celery_setup/from_celery.py
index 0ddfcc76..6561c622 100644
--- a/mediagoblin/celery_setup/from_celery.py
+++ b/mediagoblin/celery_setup/from_celery.py
@@ -18,6 +18,7 @@ import os
import mongokit
from paste.deploy.loadwsgi import NicerConfigParser
+from paste.deploy.converters import asint
from mediagoblin import storage, models
from mediagoblin.celery_setup import setup_celery_from_config
@@ -67,8 +68,11 @@ def setup_self(setup_globals_func=setup_globals):
settings_module=OUR_MODULENAME,
set_environ=False)
+ port = mgoblin_section.get('db_port')
+ if port:
+ port = asint(port)
connection = mongokit.Connection(
- mgoblin_section.get('db_host'), mgoblin_section.get('db_port'))
+ mgoblin_section.get('db_host'), port)
db = connection[mgoblin_section.get('db_name', 'mediagoblin')]
models.register_models(connection)
--
cgit v1.2.3
From 34900cce8ce0339b645d34749f6f5bed7bd5eef7 Mon Sep 17 00:00:00 2001
From: Sebastian Spaeth
Date: Sun, 8 May 2011 15:46:35 +0200
Subject: Don't escape the verification URL
In the verification email we would output the URL using HTML encoded
text, so that e.g. & -> &. We don't want that and we know the URL
won't contain user contributed content, so it is safe to turn off HTML
encoding here.
Signed-off-by: Sebastian Spaeth
---
mediagoblin/templates/mediagoblin/auth/verification_email.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/templates/mediagoblin/auth/verification_email.txt b/mediagoblin/templates/mediagoblin/auth/verification_email.txt
index ce0629eb..7863374d 100644
--- a/mediagoblin/templates/mediagoblin/auth/verification_email.txt
+++ b/mediagoblin/templates/mediagoblin/auth/verification_email.txt
@@ -19,4 +19,4 @@ Hi {{ username }},
to activate your GNU MediaGoblin account, open the following URL in your web browser
-{{ verification_url }}
+{{ verification_url|safe }}
--
cgit v1.2.3
From cd847fd346e048a4bd6c42e065475b3167991213 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 8 May 2011 10:07:39 -0500
Subject: Asbool the email debug mode option
---
mediagoblin/app.py | 4 ++--
mediagoblin/celery_setup/from_celery.py | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index 913e530e..2a2f21cc 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -18,7 +18,7 @@ import urllib
import routes
import mongokit
-from paste.deploy.converters import asint
+from paste.deploy.converters import asbool, asint
from webob import Request, exc
from mediagoblin import routing, util, models, storage, staticdirect
@@ -148,7 +148,7 @@ def paste_app_factory(global_config, **app_config):
staticdirector=staticdirector,
email_sender_address=app_config.get(
'email_sender_address', 'notice@mediagoblin.example.org'),
- email_debug_mode=app_config.get('email_debug_mode'),
+ email_debug_mode=asbool(app_config.get('email_debug_mode')),
user_template_path=app_config.get('local_templates'))
return mgoblin_app
diff --git a/mediagoblin/celery_setup/from_celery.py b/mediagoblin/celery_setup/from_celery.py
index 6561c622..55e638b9 100644
--- a/mediagoblin/celery_setup/from_celery.py
+++ b/mediagoblin/celery_setup/from_celery.py
@@ -18,7 +18,7 @@ import os
import mongokit
from paste.deploy.loadwsgi import NicerConfigParser
-from paste.deploy.converters import asint
+from paste.deploy.converters import asint, asbool
from mediagoblin import storage, models
from mediagoblin.celery_setup import setup_celery_from_config
@@ -86,7 +86,7 @@ def setup_self(setup_globals_func=setup_globals):
db_connection=connection,
database=db,
public_store=public_store,
- email_debug_mode=mgoblin_section.get('email_debug_mode'),
+ email_debug_mode=asbool(mgoblin_section.get('email_debug_mode')),
email_sender_address=mgoblin_section.get(
'email_sender_address',
'notice@mediagoblin.example.org'),
--
cgit v1.2.3
From ec61f094926c7d64bd76f7d4dc79ce859d6f60ef Mon Sep 17 00:00:00 2001
From: Sebastian Spaeth
Date: Mon, 9 May 2011 00:23:12 +0200
Subject: Fix description submission in form handling
When we submitted an image the description would remain empty. THis was
because of some weird typo in form handling. Get an attribute with
.get('description') and not with .get(['description']). With this patch,
descriptions actually go into the database.
Signed-off-by: Sebastian Spaeth
---
mediagoblin/submit/views.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 9c4eb3a4..5e262f12 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -42,7 +42,7 @@ def submit_start(request):
# create entry and save in database
entry = request.db.MediaEntry()
entry['title'] = request.POST['title']
- entry['description'] = request.POST.get(['description'])
+ entry['description'] = request.POST.get('description')
entry['media_type'] = u'image' # heh
entry['uploader'] = request.user
--
cgit v1.2.3
From 9a16e16ffa9c0477bec6ea0bf1db7efd6f988638 Mon Sep 17 00:00:00 2001
From: Sebastian Spaeth
Date: Sun, 8 May 2011 20:35:54 +0200
Subject: Implement simple media detail page
This patch creates a "homepage" for each media. The URL is
/u//m/.
On it we display the media and some details. It is ugly and lacking some
stuff but it works. The only thing left to do is to throw an 404 error
if the and the media uploader don't correspond.
- Also create a user "home page" while at it. It is merely a place
holder for now though.
- Link from the entries on the homepage, to the media pages, so we
actually find them.
Signed-off-by: Sebastian Spaeth
---
mediagoblin/routing.py | 3 +-
.../templates/mediagoblin/media_details.html | 34 ++++++++++++++
mediagoblin/templates/mediagoblin/root.html | 6 ++-
.../templates/mediagoblin/user_pages/media.html | 41 +++++++++++++++++
.../templates/mediagoblin/user_pages/user.html | 26 +++++++++++
mediagoblin/user_pages/__init__.py | 0
mediagoblin/user_pages/routing.py | 24 ++++++++++
mediagoblin/user_pages/views.py | 52 ++++++++++++++++++++++
mediagoblin/views.py | 4 +-
9 files changed, 185 insertions(+), 5 deletions(-)
create mode 100644 mediagoblin/templates/mediagoblin/media_details.html
create mode 100644 mediagoblin/templates/mediagoblin/user_pages/media.html
create mode 100644 mediagoblin/templates/mediagoblin/user_pages/user.html
create mode 100644 mediagoblin/user_pages/__init__.py
create mode 100644 mediagoblin/user_pages/routing.py
create mode 100644 mediagoblin/user_pages/views.py
diff --git a/mediagoblin/routing.py b/mediagoblin/routing.py
index b47bec8d..356ef678 100644
--- a/mediagoblin/routing.py
+++ b/mediagoblin/routing.py
@@ -18,7 +18,7 @@ from routes import Mapper
from mediagoblin.auth.routing import auth_routes
from mediagoblin.submit.routing import submit_routes
-
+from mediagoblin.user_pages.routing import user_routes
def get_mapper():
mapping = Mapper()
@@ -30,5 +30,6 @@ def get_mapper():
mapping.extend(auth_routes, '/auth')
mapping.extend(submit_routes, '/submit')
+ mapping.extend(user_routes, '/u')
return mapping
diff --git a/mediagoblin/templates/mediagoblin/media_details.html b/mediagoblin/templates/mediagoblin/media_details.html
new file mode 100644
index 00000000..a00354bc
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/media_details.html
@@ -0,0 +1,34 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+{% block mediagoblin_content %}
+
+ {# temporarily, an "image gallery" that isn't one really ;) #}
+ {% if media %}
+
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html
new file mode 100644
index 00000000..08cc9251
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html
@@ -0,0 +1,41 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+{% block mediagoblin_content %}
+
+ {# temporarily, an "image gallery" that isn't one really ;) #}
+ {% if media %}
+
+
+
+ Uploaded on {{ "%4d-%02d-%02d"|format(media.created.year,
+ media.created.month,media.created.day)}} by {{media.uploader.username}}
+ Description: {{media.description}}
+
+ {% else %}
+
Sorry, no such media found.
+ {% endif %}
+{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/user.html b/mediagoblin/templates/mediagoblin/user_pages/user.html
new file mode 100644
index 00000000..4ad34f51
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/user_pages/user.html
@@ -0,0 +1,26 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+{% block mediagoblin_content -%}
+ {% if user %}
+
User page for '{{user.username}}'
+ {{user}}
+ {% else %}
+
Sorry, no such user found.
+ {% endif %}
+{% endblock %}
diff --git a/mediagoblin/user_pages/__init__.py b/mediagoblin/user_pages/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py
new file mode 100644
index 00000000..10ecd4fd
--- /dev/null
+++ b/mediagoblin/user_pages/routing.py
@@ -0,0 +1,24 @@
+1# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+from routes.route import Route
+
+user_routes = [
+ Route('mediagoblin.user_pages.user_home', "/{user}",
+ controller="mediagoblin.user_pages.views:user_home"),
+ Route('mediagoblin.user_pages.media_home', r'/{user}/m/{m_id}',
+ requirements=dict(m_id="[0-9a-fA-F]{24}"),
+ controller="mediagoblin.user_pages.views:media_home")]
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
new file mode 100644
index 00000000..b1a301d4
--- /dev/null
+++ b/mediagoblin/user_pages/views.py
@@ -0,0 +1,52 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+from webob import Response
+from mongokit import ObjectId
+import wtforms
+#from mongokit import ObjectId
+
+def user_home(request):
+ """'Homepage' of a User()"""
+ user = request.db.User.find_one(
+ {'username': request.matchdict['user']})
+
+ medias = request.db.MediaEntry.find()
+
+ template = request.template_env.get_template(
+ 'mediagoblin/user_pages/user.html')
+ return Response(
+ template.render(
+ {'request': request,
+ 'user': user,
+ 'medias': medias}))
+
+def media_home(request):
+ """'Homepage' of a MediaEntry()"""
+ media = request.db.MediaEntry.find_one(
+ ObjectId(request.matchdict['m_id']))
+
+ #check that media uploader and user correspondent
+ if media['uploader'].get('username') != request.matchdict['user']:
+ #TODO: How do I throw an error 404?
+ pass
+
+ template = request.template_env.get_template(
+ 'mediagoblin/user_pages/media.html')
+ return Response(
+ template.render(
+ {'request': request,
+ 'media': media}))
diff --git a/mediagoblin/views.py b/mediagoblin/views.py
index 3728d4aa..f4c0598a 100644
--- a/mediagoblin/views.py
+++ b/mediagoblin/views.py
@@ -18,13 +18,13 @@ import datetime
from webob import Response, exc
import wtforms
-
+from mongokit import ObjectId
from mediagoblin import models
def root_view(request):
media_entries = request.db.MediaEntry.find(
{u'state': u'processed'})
-
+
template = request.template_env.get_template(
'mediagoblin/root.html')
return Response(
--
cgit v1.2.3
From 2eef8761d835cfbda42a9e9437ac475ddf12918a Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Tue, 10 May 2011 16:24:51 -0500
Subject: Indenting these templates because I'm pedantic about tag sections
having their content indented :)
---
mediagoblin/templates/mediagoblin/media_details.html | 18 +++++++++---------
mediagoblin/templates/mediagoblin/user_pages/user.html | 6 +++---
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/mediagoblin/templates/mediagoblin/media_details.html b/mediagoblin/templates/mediagoblin/media_details.html
index a00354bc..1b02c809 100644
--- a/mediagoblin/templates/mediagoblin/media_details.html
+++ b/mediagoblin/templates/mediagoblin/media_details.html
@@ -20,15 +20,15 @@
{# temporarily, an "image gallery" that isn't one really ;) #}
{% if media %}
-
{% endif %}
{% endblock %}
--
cgit v1.2.3
From f62494084460d09a2902ce656bf6dfda6c6b6852 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Tue, 10 May 2011 16:25:04 -0500
Subject: 404 appropriately here
---
mediagoblin/user_pages/views.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index b1a301d4..cc613c40 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -17,7 +17,7 @@
from webob import Response
from mongokit import ObjectId
import wtforms
-#from mongokit import ObjectId
+
def user_home(request):
"""'Homepage' of a User()"""
@@ -34,15 +34,15 @@ def user_home(request):
'user': user,
'medias': medias}))
+
def media_home(request):
"""'Homepage' of a MediaEntry()"""
media = request.db.MediaEntry.find_one(
ObjectId(request.matchdict['m_id']))
- #check that media uploader and user correspondent
+ #check that media uploader and user correspond
if media['uploader'].get('username') != request.matchdict['user']:
- #TODO: How do I throw an error 404?
- pass
+ return exc.HTTPNotFound()
template = request.template_env.get_template(
'mediagoblin/user_pages/media.html')
--
cgit v1.2.3
From 80c1802440380a725d4279f46be1333fe3205e6c Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Tue, 10 May 2011 16:35:34 -0500
Subject: Removing this horrifying submission test stuff from way back when
---
mediagoblin/views.py | 45 ---------------------------------------------
1 file changed, 45 deletions(-)
diff --git a/mediagoblin/views.py b/mediagoblin/views.py
index f4c0598a..95d0be7a 100644
--- a/mediagoblin/views.py
+++ b/mediagoblin/views.py
@@ -31,48 +31,3 @@ def root_view(request):
template.render(
{'request': request,
'media_entries': media_entries}))
-
-
-class ImageSubmitForm(wtforms.Form):
- title = wtforms.TextField(
- 'Title',
- [wtforms.validators.Length(min=1, max=500)])
- description = wtforms.TextAreaField('Description of this work')
- file = wtforms.FileField('File')
-
-
-def submit_test(request):
- image_form = ImageSubmitForm(request.POST)
- if request.method == 'POST' and image_form.validate():
- # create entry and save in database
-
- entry = request.db.MediaEntry()
- entry['title'] = request.POST['title']
- entry['description'] = request.POST.get(['description'])
- entry['media_type'] = u'image'
-
- # TODO this does NOT look save, we should clean the filename somenow?
- entry['file_store'] = request.POST['file'].filename
-
- entry.save(validate=True)
-
- # save file to disk
- ## TODO
- #open('/tmp/read_file.png', 'wb').write(request.POST['file'].file.read())
-
-
- # resize if necessary
- ## Hm. This should be done on a separate view?
-
- # redirect
- pass
-
-
-
- # render
- template = request.template_env.get_template(
- 'mediagoblin/test_submit.html')
- return Response(
- template.render(
- {'request': request,
- 'image_form': image_form}))
--
cgit v1.2.3
From 7222955fbad9d21542e71dafa910973a9cb0e676 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Wed, 11 May 2011 10:26:15 -0500
Subject: URLs should end in trailing slashes, or slash redirection doesn't
work
---
mediagoblin/user_pages/routing.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py
index 10ecd4fd..c2dc2fc0 100644
--- a/mediagoblin/user_pages/routing.py
+++ b/mediagoblin/user_pages/routing.py
@@ -1,4 +1,4 @@
-1# GNU MediaGoblin -- federated, autonomous media hosting
+# GNU MediaGoblin -- federated, autonomous media hosting
# Copyright (C) 2011 Free Software Foundation, Inc
#
# This program is free software: you can redistribute it and/or modify
@@ -17,8 +17,8 @@
from routes.route import Route
user_routes = [
- Route('mediagoblin.user_pages.user_home', "/{user}",
+ Route('mediagoblin.user_pages.user_home', "/{user}/",
controller="mediagoblin.user_pages.views:user_home"),
- Route('mediagoblin.user_pages.media_home', r'/{user}/m/{m_id}',
+ Route('mediagoblin.user_pages.media_home', r'/{user}/m/{m_id}/',
requirements=dict(m_id="[0-9a-fA-F]{24}"),
controller="mediagoblin.user_pages.views:media_home")]
--
cgit v1.2.3
From d483b9b4734d271e2b37cd586e22fdad014c9386 Mon Sep 17 00:00:00 2001
From: Sebastian Spaeth
Date: Mon, 9 May 2011 01:08:46 +0200
Subject: Enforce using local dateutil with buildout
Natty has a too old system dateutil, but buildout will put the system
modules in the search path first. By adding the dateutil spec to the
'egg' requirement, we put the dateutil inclusion of the local egg first
and natty compiles (buildouts) fine.
Part of http://bugs.foocorp.net/issues/308
Signed-off-by: Sebastian Spaeth
---
buildout.cfg | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/buildout.cfg b/buildout.cfg
index 520d5907..a77bf93c 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -6,7 +6,9 @@ parts = mediagoblin make_user_dev_dirs
recipe=zc.recipe.egg
interpreter=python
dependent-scripts = true
-eggs=mediagoblin
+eggs=
+ python-dateutil>=1.5.0,<2.0.0
+ mediagoblin
entry-points =
nosetests=nose:run_exit
paster=paste.script.command:run
--
cgit v1.2.3
From 6557056bca7e4bd722212cd9d217dbb23ce8aebd Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 07:14:15 -0500
Subject: I don't believe we need READMEish.org anymore.
---
READMEish.org | 192 ----------------------------------------------------------
1 file changed, 192 deletions(-)
delete mode 100644 READMEish.org
diff --git a/READMEish.org b/READMEish.org
deleted file mode 100644
index c4e95122..00000000
--- a/READMEish.org
+++ /dev/null
@@ -1,192 +0,0 @@
-#+latex_header: \documentclass[12pt]{article}
-#+latex_header: \usepackage[margin=1in]{geometry}
-#+OPTIONS: ^:nil
-
-GNU MediaGoblin
-
-* About
-
-What is MediaGoblin? I'm shooting for:
-
- - Initially, a place to store all your photos that's as awesome as,
- more awesome than, existing proprietary solutions
- - Later, a place for all sorts of media, such as video, music, etc
- hosting.
- - Federated, like statusnet/ostatus (we should use ostatus, in fact!)
- - Customizable
- - A place for people to collaborate and show off original and derived
- creations
- - Free, as in freedom. Under the GNU AGPL, v3 or later. Encourages
- free formats and free licensing for content, too.
-
-Wow! That's pretty ambitious. Hopefully we're cool enough to do it.
-I think we can.
-
-It's also necessary, for multiple reasons. Centralization and
-proprietization of media on the internet is a serious problem and
-makes the web go from a system of extreme resilience to a system
-of frightening fragility. People should be able to own their data.
-Etc. If you're reading this, chances are you already agree though. :)
-
-* Milestones
-
-Excepting the first, not necessarily in this order.
-
-** Basic image hosting
-** Multi-media hosting (including video and audio)
-** API(s)
-** Federation
-
-Maybe this is 0.2 :)
-
-** Plugin system
-
-* Technology
-
-I have a pretty specific set of tools that I expect to use in this
-project. Those are:
-
- - *[[http://python.org/][Python]]:* because I love, and know well, the language
- - *[[http://www.mongodb.org/][MongoDB]]:* a "document database". Because it's extremely flexible
- (and scales up well, but I guess not down well)
- - *[[http://namlook.github.com/mongokit/][MongoKit]]:* a lightweight ORM for mongodb. Helps us define our
- structures better, does schema validation, schema evolution, and
- helps make things more fun and pythonic.
- - *[[http://jinja.pocoo.org/docs/][Jinja2]]:* for templating. Pretty much django templates++ (wow, I
- can actually pass arguments into method calls instead of tediously
- writing custom tags!)
- - *[[http://wtforms.simplecodes.com/][WTForms]]:* for form handling, validation, abstraction. Almost just
- like Django's templates,
- - *[[http://pythonpaste.org/webob/][WebOb]]:* gives nice request/response objects (also somewhat djangoish)
- - *[[http://pythonpaste.org/deploy/][Paste Deploy]] and [[http://pythonpaste.org/script/][Paste Script]]:* as the default way of configuring
- and launching the application. Since MediaGoblin will be fairly
- wsgi minimalist though, you can probably use other ways to launch
- it, though this will be the default.
- - *[[http://routes.groovie.org/][Routes]]:* for URL routing. It works well enough.
- - *[[http://jquery.com/][JQuery]]:* for all sorts of things on the javascript end of things,
- for all sorts of reasons.
- - *[[http://beaker.groovie.org/][Beaker]]:* for sessions, because that seems like it's generally
- considered the way to go I guess.
- - *[[http://somethingaboutorange.com/mrl/projects/nose/1.0.0/][nose]]:* for unit tests, because it makes testing a bit nicer.
- - *[[http://celeryproject.org/][Celery]]:* for task queueing (think resizing images, encoding
- video) because some people like it, and even the people I know who
- don't don't seem to know of anything better :)
- - *[[http://www.rabbitmq.com/][RabbitMQ]]:* for sending tasks to celery, because I guess that's
- what most people do. Might be optional, might also let people use
- MongoDB for this if they want.
-
-** Why python
-
-Because I (Chris Webber) know Python, love Python, am capable of
-actually making this thing happen in Python (I've worked on a lot of
-large free software web applications before in Python, including
-[[http://mirocommunity.org/][Miro Community]], the [[http://miroguide.org][Miro Guide]], a large portion of
-[[http://creativecommons.org/][Creative Commons' site]], and a whole bunch of things while working at
-[[http://www.imagescape.com/][Imaginary Landscape]]). I know Python, I can make this happen in
-Python, me starting a project like this makes sense if it's done in
-Python.
-
-You might say that PHP is way more deployable, that rails has way more
-cool developers riding around on fixie bikes, and all of those things
-are true, but I know Python, like Python, and think that Python is
-pretty great. I do think that deployment in Python is not as good as
-with PHP, but I think the days of shared hosting are (thankfully)
-coming to an end, and will probably be replaced by cheap virtual
-machines spun up on the fly for people who want that sort of stuff,
-and Python will be a huge part of that future, maybe even more than
-PHP will. The deployment tools are getting better. Maybe we can use
-something like Silver Lining. Maybe we can just distribute as .debs
-or .rpms. We'll figure it out.
-
-But if I'm starting this project, which I am, it's gonna be in Python.
-
-** Why mongodb
-
-In case you were wondering, I am not a NOSQL fanboy, I do not go
-around telling people that MongoDB is web scale. Actually my choice
-for MongoDB isn't scalability, though scaling up really nicely is a
-pretty good feature and sets us up well in case large volume sites
-eventually do use MediaGoblin. But there's another side of
-scalability, and that's scaling down, which is important for
-federation, maybe even more important than scaling up in an ideal
-universe where everyone ran servers out of their own housing. As a
-memory-mapped database, MongoDB is pretty hungry, so actually I spent
-a lot of time debating whether the inability to scale down as nicely
-as something like SQL has with sqlite meant that it was out.
-
-But I decided in the end that I really want MongoDB, not for
-scalability, but for flexibility. Schema evolution pains in SQL are
-almost enough reason for me to want MongoDB, but not quite. The real
-reason is because I want the ability to eventually handle multiple
-media types through MediaGoblin, and also allow for plugins, without
-the rigidity of tables making that difficult. In other words,
-something like:
-
-#+BEGIN_SRC javascript
-{"title": "Me talking until you are bored",
- "description": "blah blah blah",
- "media_type": "audio",
- "media_data": {
- "length": "2:30",
- "codec": "OGG Vorbis"},
- "plugin_data": {
- "licensing": {
- "license": "http://creativecommons.org/licenses/by-sa/3.0/"}}}
-#+END_SRC
-
-Being able to just dump media-specific information in a media_data
-hashtable is pretty great, and even better is having a plugin system
-where you can just let plugins have their own entire key-value space
-cleanly inside the document that doesn't interfere with anyone else's
-stuff. If we were to let plugins to deposit their own information
-inside the database, either we'd let plugins create their own tables
-which makes SQL migrations even harder than they already are, or we'd
-probably end up creating a table with a column for key, a column for
-value, and a column for type in one huge table called "plugin_data" or
-something similar. (Yo dawg, I heard you liked plugins, so I put a
-database in your database so you can query while you query.) Gross.
-
-I also don't want things to be too lose so that we forget or lose the
-structure of things, and that's one reason why I want to use MongoKit,
-because we can cleanly define a much structure as we want and verify
-that documents match that structure generally without adding too much
-bloat or overhead (mongokit is a pretty lightweight wrapper and
-doesn't inject extra mongokit-specific stuff into the database, which
-is nice and nicer than many other ORMs in that way).
-
-** Why wsgi minimalism / Why not Django
-
-If you notice in the technology list above, I list a lot of components
-that are very [[http://www.djangoproject.com/][Django-like]], but not actually Django components. What
-can I say, I really like a lot of the ideas in Django! Which leads to
-the question: why not just use Django?
-
-While I really like Django's ideas and a lot of its components, I also
-feel that most of the best ideas in Django I want have been
-implemented as good or even better outside of Django. I could just
-use Django and replace the templating system with Jinja2, and the form
-system with wtforms, and the database with MongoDB and MongoKit, but
-at that point, how much of Django is really left?
-
-I also am sometimes saddened and irritated by how coupled all of
-Django's components are. Loosely coupled yes, but still coupled.
-WSGI has done a good job of providing a base layer for running
-applications on and [[http://pythonpaste.org/webob/do-it-yourself.html][if you know how to do it yourself]] it's not hard or
-many lines of code at all to bind them together without any framework
-at all (not even say [[http://pylonshq.com/][Pylons]], [[http://docs.pylonsproject.org/projects/pyramid/dev/][Pyramid]], or [[http://flask.pocoo.org/][Flask]] which I think are still
-great projects, especially for people who want this sort of thing but
-have no idea how to get started). And even at this already really
-early stage of writing MediaGoblin, that glue work is mostly done.
-
-Not to say I don't think Django isn't great for a lot of things. For
-a lot of stuff, it's still the best, but not for MediaGoblin, I think.
-
-One thing that Django does super well though is documentation. It
-still has some faults, but even with those considered I can hardly
-think of any other project in Python that has as nice of documentation
-as Django. It may be worth
-[[http://pycon.blip.tv/file/4881071/][learning some lessons on documentation from Django]], on that note.
-
-I'd really like to have a good, thorough hacking-howto and
-deployment-howto, especially in the former making some notes on how to
-make it easier for Django hackers to get started.
--
cgit v1.2.3
From 1504acfddf8e84383733dae33bf6bfbd7ae3df8d Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 07:15:11 -0500
Subject: Right, we don't need the exported HTML either.
---
READMEish.html | 426 ---------------------------------------------------------
1 file changed, 426 deletions(-)
delete mode 100644 READMEish.html
diff --git a/READMEish.html b/READMEish.html
deleted file mode 100644
index 9981da11..00000000
--- a/READMEish.html
+++ /dev/null
@@ -1,426 +0,0 @@
-
-
-
-
-GNU MediaGoblin
-
-
-
-
-
-
-
-
-
-
-
-
Initially, a place to store all your photos that's as awesome as,
- more awesome than, existing proprietary solutions
-
-
Later, a place for all sorts of media, such as video, music, etc
- hosting.
-
-
Federated, like statusnet/ostatus (we should use ostatus, in fact!)
-
-
Customizable
-
-
A place for people to collaborate and show off original and derived
- creations
-
-
Free, as in freedom. Under the GNU AGPL, v3 or later. Encourages
- free formats and free licensing for content, too.
-
-
-
-
-Wow! That's pretty ambitious. Hopefully we're cool enough to do it.
-I think we can.
-
-
-It's also necessary, for multiple reasons. Centralization and
-proprietization of media on the internet is a serious problem and
-makes the web go from a system of extreme resilience to a system
-of frightening fragility. People should be able to own their data.
-Etc. If you're reading this, chances are you already agree though. :)
-
-
-
-
-
-
-
2 Milestones
-
-
-
-
-Excepting the first, not necessarily in this order.
-
-
-
-
-
-
2.1 Basic image hosting
-
-
-
-
-
-
-
-
2.2 Multi-media hosting (including video and audio)
-
-
-
-
-
-
-
-
2.3 API(s)
-
-
-
-
-
-
-
-
2.4 Federation
-
-
-
-
-Maybe this is 0.2 :)
-
-
-
-
-
-
-
2.5 Plugin system
-
-
-
-
-
-
-
-
-
-
3 Technology
-
-
-
-
-I have a pretty specific set of tools that I expect to use in this
-project. Those are:
-
-
-
Python: because I love, and know well, the language
-
-
MongoDB: a "document database". Because it's extremely flexible
- (and scales up well, but I guess not down well)
-
-
MongoKit: a lightweight ORM for mongodb. Helps us define our
- structures better, does schema validation, schema evolution, and
- helps make things more fun and pythonic.
-
-
Jinja2: for templating. Pretty much django templates++ (wow, I
- can actually pass arguments into method calls instead of tediously
- writing custom tags!)
-
-
WTForms: for form handling, validation, abstraction. Almost just
- like Django's templates,
-
Paste Deploy and Paste Script: as the default way of configuring
- and launching the application. Since MediaGoblin will be fairly
- wsgi minimalist though, you can probably use other ways to launch
- it, though this will be the default.
-
JQuery: for all sorts of things on the javascript end of things,
- for all sorts of reasons.
-
-
Beaker: for sessions, because that seems like it's generally
- considered the way to go I guess.
-
-
nose: for unit tests, because it makes testing a bit nicer.
-
-
Celery: for task queueing (think resizing images, encoding
- video) because some people like it, and even the people I know who
- don't don't seem to know of anything better :)
-
-
RabbitMQ: for sending tasks to celery, because I guess that's
- what most people do. Might be optional, might also let people use
- MongoDB for this if they want.
-
-
-
-
-
-
-
-
3.1 Why python
-
-
-
-
-Because I (Chris Webber) know Python, love Python, am capable of
-actually making this thing happen in Python (I've worked on a lot of
-large free software web applications before in Python, including
-Miro Community, the Miro Guide, a large portion of
-Creative Commons' site, and a whole bunch of things while working at
-Imaginary Landscape). I know Python, I can make this happen in
-Python, me starting a project like this makes sense if it's done in
-Python.
-
-
-You might say that PHP is way more deployable, that rails has way more
-cool developers riding around on fixie bikes, and all of those things
-are true, but I know Python, like Python, and think that Python is
-pretty great. I do think that deployment in Python is not as good as
-with PHP, but I think the days of shared hosting are (thankfully)
-coming to an end, and will probably be replaced by cheap virtual
-machines spun up on the fly for people who want that sort of stuff,
-and Python will be a huge part of that future, maybe even more than
-PHP will. The deployment tools are getting better. Maybe we can use
-something like Silver Lining. Maybe we can just distribute as .debs
-or .rpms. We'll figure it out.
-
-
-But if I'm starting this project, which I am, it's gonna be in Python.
-
-
-
-
-
-
-
3.2 Why mongodb
-
-
-
-
-In case you were wondering, I am not a NOSQL fanboy, I do not go
-around telling people that MongoDB is web scale. Actually my choice
-for MongoDB isn't scalability, though scaling up really nicely is a
-pretty good feature and sets us up well in case large volume sites
-eventually do use MediaGoblin. But there's another side of
-scalability, and that's scaling down, which is important for
-federation, maybe even more important than scaling up in an ideal
-universe where everyone ran servers out of their own housing. As a
-memory-mapped database, MongoDB is pretty hungry, so actually I spent
-a lot of time debating whether the inability to scale down as nicely
-as something like SQL has with sqlite meant that it was out.
-
-
-But I decided in the end that I really want MongoDB, not for
-scalability, but for flexibility. Schema evolution pains in SQL are
-almost enough reason for me to want MongoDB, but not quite. The real
-reason is because I want the ability to eventually handle multiple
-media types through MediaGoblin, and also allow for plugins, without
-the rigidity of tables making that difficult. In other words,
-something like:
-
-Being able to just dump media-specific information in a media_data
-hashtable is pretty great, and even better is having a plugin system
-where you can just let plugins have their own entire key-value space
-cleanly inside the document that doesn't interfere with anyone else's
-stuff. If we were to let plugins to deposit their own information
-inside the database, either we'd let plugins create their own tables
-which makes SQL migrations even harder than they already are, or we'd
-probably end up creating a table with a column for key, a column for
-value, and a column for type in one huge table called "plugin_data" or
-something similar. (Yo dawg, I heard you liked plugins, so I put a
-database in your database so you can query while you query.) Gross.
-
-
-I also don't want things to be too lose so that we forget or lose the
-structure of things, and that's one reason why I want to use MongoKit,
-because we can cleanly define a much structure as we want and verify
-that documents match that structure generally without adding too much
-bloat or overhead (mongokit is a pretty lightweight wrapper and
-doesn't inject extra mongokit-specific stuff into the database, which
-is nice and nicer than many other ORMs in that way).
-
-
-
-
-
-
-
3.3 Why wsgi minimalism / Why not Django
-
-
-
-
-If you notice in the technology list above, I list a lot of components
-that are very Django-like, but not actually Django components. What
-can I say, I really like a lot of the ideas in Django! Which leads to
-the question: why not just use Django?
-
-
-While I really like Django's ideas and a lot of its components, I also
-feel that most of the best ideas in Django I want have been
-implemented as good or even better outside of Django. I could just
-use Django and replace the templating system with Jinja2, and the form
-system with wtforms, and the database with MongoDB and MongoKit, but
-at that point, how much of Django is really left?
-
-
-I also am sometimes saddened and irritated by how coupled all of
-Django's components are. Loosely coupled yes, but still coupled.
-WSGI has done a good job of providing a base layer for running
-applications on and if you know how to do it yourself it's not hard or
-many lines of code at all to bind them together without any framework
-at all (not even say Pylons, Pyramid, or Flask which I think are still
-great projects, especially for people who want this sort of thing but
-have no idea how to get started). And even at this already really
-early stage of writing MediaGoblin, that glue work is mostly done.
-
-
-Not to say I don't think Django isn't great for a lot of things. For
-a lot of stuff, it's still the best, but not for MediaGoblin, I think.
-
-
-One thing that Django does super well though is documentation. It
-still has some faults, but even with those considered I can hardly
-think of any other project in Python that has as nice of documentation
-as Django. It may be worth
-learning some lessons on documentation from Django, on that note.
-
-
-I'd really like to have a good, thorough hacking-howto and
-deployment-howto, especially in the former making some notes on how to
-make it easier for Django hackers to get started.
-
-
-
--
cgit v1.2.3
From 829d50f350bf9a98580a01906218aca150b1ea89 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 07:17:02 -0500
Subject: Fixing tyop in README... thanks Daniel Neel!
Also clarifying that our public alpha may be in October, which is what
we've said elsewhere.
---
README | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README b/README
index c6e073a0..2ef6f78e 100644
--- a/README
+++ b/README
@@ -12,7 +12,7 @@ What is GNU MediaGoblin?
* Federated with OStatus!
* Customizable!
* A place for people to collaborate and show off original and derived
- creations Free, as in freedom. We’re a GNU project in the making,
+ creations. Free, as in freedom. We’re a GNU project in the making,
afterall.
@@ -20,7 +20,7 @@ Is it ready for me to use?
==========================
Not yet! We're working on it and we hope to have a usable system by
-September 2011.
+September / October 2011.
Can I help/hang out/participate/whisper sweet nothings in your ear?
--
cgit v1.2.3
From 20c834ffe409c55e7e9dc6e4110f90f7dd177f35 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 09:18:53 -0500
Subject: Add the jinja2 extension to the jinja loader
---
mediagoblin/util.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index 8695180a..63f0f9c5 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -48,7 +48,9 @@ def get_jinja_env(user_template_path=None):
else:
loader = jinja2.PackageLoader('mediagoblin', 'templates')
- return jinja2.Environment(loader=loader, autoescape=True)
+ return jinja2.Environment(
+ loader=loader, autoescape=True,
+ extensions=['jinja2.ext.i18n'])
def setup_user_in_request(request):
@@ -180,3 +182,4 @@ def send_email(from_addr, to_addrs, subject, message_body):
else:
return mhost.sendmail(from_addr, to_addrs, message.as_string())
+
--
cgit v1.2.3
From 84d4f04edc468ba24685158fe379d37acb0db538 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 09:44:04 -0500
Subject: Added extraction stuff that's not used but appears to work :)
---
babel.ini | 13 +++++++++++++
setup.py | 4 ++++
2 files changed, 17 insertions(+)
create mode 100644 babel.ini
diff --git a/babel.ini b/babel.ini
new file mode 100644
index 00000000..666270df
--- /dev/null
+++ b/babel.ini
@@ -0,0 +1,13 @@
+# Extraction from Python source files
+[python: mediagoblin/**.py]
+# Extraction from Genshi HTML and text templates
+[jinja2: mediagoblin/templates/**.html]
+# Extract jinja templates (html)
+encoding = utf-8
+[jinja2: mediagoblin/templates/**.txt]
+# Extract jinja templates (text)
+encoding = utf-8
+
+# # Extraction from JavaScript files
+# [javascript: mediagoblin/static/js/**.js]
+# extract_messages = $._, jQuery._
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 7b483a57..7d38e526 100644
--- a/setup.py
+++ b/setup.py
@@ -38,6 +38,7 @@ setup(
'jinja2',
'sphinx',
'PIL',
+ 'Babel',
],
test_suite='nose.collector',
@@ -50,5 +51,8 @@ setup(
[zc.buildout]
make_user_dev_dirs = mediagoblin.buildout_recipes:MakeUserDevDirs
+
+ [babel.extractors]
+ jinja2 = jinja2.ext:babel_extract
""",
)
--
cgit v1.2.3
From 36bb98fbbad56d6721c73d7b8877e8d2856d7578 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 09:48:54 -0500
Subject: Translate the welcome message (extracts successfully!)
---
mediagoblin/templates/mediagoblin/root.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html
index 2cb0a9c0..e833e3fe 100644
--- a/mediagoblin/templates/mediagoblin/root.html
+++ b/mediagoblin/templates/mediagoblin/root.html
@@ -18,7 +18,7 @@
{% extends "mediagoblin/base.html" %}
{% block mediagoblin_content %}
-
Welcome to GNU MediaGoblin!
+
{% trans %}Welcome to GNU MediaGoblin!{% endtrans %}
{% if request.user %}
--
cgit v1.2.3
From 95aa6b56b29eb59ea14acad078e645af0a35e5b9 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 10:05:35 -0500
Subject: buildout instructions come first since it's easier if it does work
---
docs/hackinghowto.rst | 21 +++++++++------------
1 file changed, 9 insertions(+), 12 deletions(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index d829b1c0..b34ce93a 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -215,14 +215,13 @@ To do this, do::
Running the server
==================
-If you did virtualenv, run::
-
- paster serve mediagoblin.ini --reload
-
If you did buildout, run::
./bin/paster serve mediagoblin.ini --reload
+If you did virtualenv, run::
+
+ paster serve mediagoblin.ini --reload
Running celeryd
===============
@@ -231,26 +230,24 @@ You need to do this if you want your media to process and actually
show up. It's probably a good idea in development to have the web
server (above) running in one terminal and celeryd in another window.
-If you did virtualenv, run::
-
- CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_celery celeryd
-
If you did buildout, run::
CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_celery ./bin/celeryd
+If you did virtualenv, run::
+
+ CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_celery celeryd
Running the test suite
======================
-If you did virtualenv, run::
-
- nosetests
-
If you did buildout, run::
./bin/nosetests
+If you did virtualenv, run::
+
+ nosetests
Troubleshooting
===============
--
cgit v1.2.3
From 1fc336e7e5c3fb385888976d740eb4df791a701d Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 10:20:03 -0500
Subject: adding master.po translations file
---
translations/master.po | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
create mode 100644 translations/master.po
diff --git a/translations/master.po b/translations/master.po
new file mode 100644
index 00000000..0e242fee
--- /dev/null
+++ b/translations/master.po
@@ -0,0 +1,23 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+# FIRST AUTHOR , 2011.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2011-05-12 10:17-0500\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+
+#: mediagoblin/templates/mediagoblin/root.html:21
+msgid "Welcome to GNU MediaGoblin!"
+msgstr ""
+
--
cgit v1.2.3
From 23d23dcf6bbf136eed0759515da73eff08dd328f Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 10:22:56 -0500
Subject: Moving translations to mediagoblin/translations
---
mediagoblin/translations/master.po | 23 +++++++++++++++++++++++
translations/master.po | 23 -----------------------
2 files changed, 23 insertions(+), 23 deletions(-)
create mode 100644 mediagoblin/translations/master.po
delete mode 100644 translations/master.po
diff --git a/mediagoblin/translations/master.po b/mediagoblin/translations/master.po
new file mode 100644
index 00000000..0e242fee
--- /dev/null
+++ b/mediagoblin/translations/master.po
@@ -0,0 +1,23 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+# FIRST AUTHOR , 2011.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2011-05-12 10:17-0500\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+
+#: mediagoblin/templates/mediagoblin/root.html:21
+msgid "Welcome to GNU MediaGoblin!"
+msgstr ""
+
diff --git a/translations/master.po b/translations/master.po
deleted file mode 100644
index 0e242fee..00000000
--- a/translations/master.po
+++ /dev/null
@@ -1,23 +0,0 @@
-# Translations template for PROJECT.
-# Copyright (C) 2011 ORGANIZATION
-# This file is distributed under the same license as the PROJECT project.
-# FIRST AUTHOR , 2011.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PROJECT VERSION\n"
-"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2011-05-12 10:17-0500\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
-
-#: mediagoblin/templates/mediagoblin/root.html:21
-msgid "Welcome to GNU MediaGoblin!"
-msgstr ""
-
--
cgit v1.2.3
From 5e593201a6b85ad3860d8b230dc7ff34c0397146 Mon Sep 17 00:00:00 2001
From: Daniel Neel
Date: Thu, 12 May 2011 14:23:52 -0400
Subject: Fixed a typo in docs/mediagoblin.rst
"...their data and that measn someone..."
> "...their data and that means someone..."
---
docs/mediagoblin.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/mediagoblin.rst b/docs/mediagoblin.rst
index df2190c1..1b17d606 100644
--- a/docs/mediagoblin.rst
+++ b/docs/mediagoblin.rst
@@ -26,7 +26,7 @@ Why are we doing this?
Centralization and proprietization of media on the internet is a
serious problem and makes the web go from a system of extreme
resilience to a system of frightening fragility. We believe people
-should be able to own their data and that measn someone has to build
+should be able to own their data and that means someone has to build
the tools to make it possible. We decide that in this case, that
someone would be us!
--
cgit v1.2.3
From 49fa1a00731418b227d5a41c0867d1c548bcd9f4 Mon Sep 17 00:00:00 2001
From: Daniel Neel
Date: Thu, 12 May 2011 14:29:54 -0400
Subject: Fixed another typo in docs/mediagoblin.rst
"We decide that in this case, that someone would be us!"
> "We decided that in this case, that someone would be us!"
---
docs/mediagoblin.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/mediagoblin.rst b/docs/mediagoblin.rst
index 1b17d606..ea9c83a7 100644
--- a/docs/mediagoblin.rst
+++ b/docs/mediagoblin.rst
@@ -27,7 +27,7 @@ Centralization and proprietization of media on the internet is a
serious problem and makes the web go from a system of extreme
resilience to a system of frightening fragility. We believe people
should be able to own their data and that means someone has to build
-the tools to make it possible. We decide that in this case, that
+the tools to make it possible. We decided that in this case, that
someone would be us!
--
cgit v1.2.3
From c19eed5283aa3a389f4f4f3e9958575797f1132b Mon Sep 17 00:00:00 2001
From: Daniel Neel
Date: Thu, 12 May 2011 14:35:39 -0400
Subject: Fixed a typo in docs/contributinghowto.rst
"it'd" > "it's"
---
docs/contributinghowto.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/contributinghowto.rst b/docs/contributinghowto.rst
index 56a80b91..e980a5e0 100644
--- a/docs/contributinghowto.rst
+++ b/docs/contributinghowto.rst
@@ -59,7 +59,7 @@ Here are some things you can do today:
**Spread the word**
The seductive call of Free Software services is a powerful
- one, but many cannot hear it because it'd drowned out by the
+ one, but many cannot hear it because it's drowned out by the
rush hour traffic honking of proprietary walled gardens and
faux free services. Yuck! Be the sweet chirrup of the bird
amidst the din! Tell others that there is a better way to
--
cgit v1.2.3
From 016617a6c943f75da4acff1eb5703ae900ccf7c8 Mon Sep 17 00:00:00 2001
From: Daniel Neel
Date: Thu, 12 May 2011 14:46:02 -0400
Subject: Changed "Foreward" to "Foreword"
Figured this was a typo. If not, feel free to skip this commit.
---
docs/foreward.rst | 46 ----------------------------------------------
1 file changed, 46 deletions(-)
delete mode 100644 docs/foreward.rst
diff --git a/docs/foreward.rst b/docs/foreward.rst
deleted file mode 100644
index d2b9c417..00000000
--- a/docs/foreward.rst
+++ /dev/null
@@ -1,46 +0,0 @@
-==========
- Foreward
-==========
-
-About this manual
-=================
-
-This is the GNU MediaGoblin manual. This documentation targets the
-following groups of individuals:
-
-* people who want to use the software
-* people who want to deploy the software
-* contributors
-
-This manual is a living document and is in the ``mediagoblin``
-repository in the ``docs/`` directory.
-
-
-Who wrote this documentation?
-=============================
-
-In no particular order:
-
-* Chris
-* Will
-* Deb
-* Greg
-* Karen
-* Matt
-* Asheesh
-
-
-I found an error in the docs---who do I tell?
-=============================================
-
-There are a few ways---please pick the one most convenient to you!
-
-1. Write up a bug report in the bug tracker at http://bugs.foocorp.net/ .
-2. Tell someone on IRC ``#mediagoblin`` on Freenode.
-3. Send an email to Will ``willg at bluesock dot org``.
-
-When you tell us about your issue, please let us know:
-
-* where you are looking (in git? url of the web-page?)
-* what the issue is
-* your thoughts on how to resolve it
--
cgit v1.2.3
From c6d266f6518673ded665d7aa63c91c2aaf7dc403 Mon Sep 17 00:00:00 2001
From: Daniel Neel
Date: Thu, 12 May 2011 14:46:59 -0400
Subject: Fixed previous broken commit
Made a mistake with the last commit, fixed here.
---
docs/foreword.rst | 46 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
create mode 100644 docs/foreword.rst
diff --git a/docs/foreword.rst b/docs/foreword.rst
new file mode 100644
index 00000000..1d423f08
--- /dev/null
+++ b/docs/foreword.rst
@@ -0,0 +1,46 @@
+==========
+ Foreword
+==========
+
+About this manual
+=================
+
+This is the GNU MediaGoblin manual. This documentation targets the
+following groups of individuals:
+
+* people who want to use the software
+* people who want to deploy the software
+* contributors
+
+This manual is a living document and is in the ``mediagoblin``
+repository in the ``docs/`` directory.
+
+
+Who wrote this documentation?
+=============================
+
+In no particular order:
+
+* Chris
+* Will
+* Deb
+* Greg
+* Karen
+* Matt
+* Asheesh
+
+
+I found an error in the docs---who do I tell?
+=============================================
+
+There are a few ways---please pick the one most convenient to you!
+
+1. Write up a bug report in the bug tracker at http://bugs.foocorp.net/ .
+2. Tell someone on IRC ``#mediagoblin`` on Freenode.
+3. Send an email to Will ``willg at bluesock dot org``.
+
+When you tell us about your issue, please let us know:
+
+* where you are looking (in git? url of the web-page?)
+* what the issue is
+* your thoughts on how to resolve it
--
cgit v1.2.3
From 434fb405e3f0c3e6ff22a6a1fcf91fc84bbdca86 Mon Sep 17 00:00:00 2001
From: Daniel Neel
Date: Thu, 12 May 2011 14:48:50 -0400
Subject: Updated table of contents
Updated TOC to match "Foreward" > "Foreword"
---
docs/index.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/index.rst b/docs/index.rst
index 16c8ca16..2f84d6a6 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -11,7 +11,7 @@ Table of Contents:
.. toctree::
:maxdepth: 2
- foreward
+ foreword
mediagoblin
contributinghowto
deploymenthowto
--
cgit v1.2.3
From 84440a68f71eb4cb3bf036ea9918ec28948cacd1 Mon Sep 17 00:00:00 2001
From: Daniel Neel
Date: Thu, 12 May 2011 14:52:51 -0400
Subject: Edits to "What's where" diagram in docs/codebase.rst
Added comment symbols to distinguish comments from directory names.
Changed wording a bit on one part.
---
docs/codebase.rst | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/docs/codebase.rst b/docs/codebase.rst
index 1f6ce220..37eaf4d2 100644
--- a/docs/codebase.rst
+++ b/docs/codebase.rst
@@ -79,22 +79,22 @@ After you've run buildout, you're faced with the following directory
tree::
mediagoblin/
- |- mediagoblin/ source code
+ |- mediagoblin/ #source code
| |- tests/
| |- templates/
| |- auth/
| \- submit/
- |- docs/ documentation
+ |- docs/ #documentation
|
- | the rest of these directories are generated by
+ | #the below directories are generated by
| buildout.
|
- |- bin/ scripts
+ |- bin/ #scripts
|- develop-eggs/
|- eggs/
|- mediagoblin.egg-info/
|- parts/
- |- user_dev/ sessions, etc
+ |- user_dev/ #sessions, etc
As you can see, all the code for GNU MediaGoblin is in the
--
cgit v1.2.3
From bdcd615c3cf290565025a46aa03f986c472be7fc Mon Sep 17 00:00:00 2001
From: Daniel Neel
Date: Thu, 12 May 2011 14:54:59 -0400
Subject: Update to previous commit
To add an extra comment symbol.
---
docs/codebase.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/codebase.rst b/docs/codebase.rst
index 37eaf4d2..4f5f215f 100644
--- a/docs/codebase.rst
+++ b/docs/codebase.rst
@@ -87,7 +87,7 @@ tree::
|- docs/ #documentation
|
| #the below directories are generated by
- | buildout.
+ | #buildout.
|
|- bin/ #scripts
|- develop-eggs/
--
cgit v1.2.3
From 2de317f2f35cfceffdda2c3990ad32b661161fb8 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 14:25:28 -0500
Subject: I probably shouldn't break the main page since we don't have the
gettext thing in place yet.
---
mediagoblin/templates/mediagoblin/root.html | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html
index e833e3fe..44d26a65 100644
--- a/mediagoblin/templates/mediagoblin/root.html
+++ b/mediagoblin/templates/mediagoblin/root.html
@@ -18,7 +18,10 @@
{% extends "mediagoblin/base.html" %}
{% block mediagoblin_content %}
-
{% trans %}Welcome to GNU MediaGoblin!{% endtrans %}
+
+
Welcome to GNU MediaGoblin!
+ {#
+
{% trans %}Welcome to GNU MediaGoblin!{% endtrans %}
#}
{% if request.user %}
--
cgit v1.2.3
From 21919313dfc18c9f9303cbbb2591c0410379f768 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 14:49:37 -0500
Subject: Fix the email debug inbox
---
mediagoblin/util.py | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index 63f0f9c5..946216ba 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -172,7 +172,7 @@ def send_email(from_addr, to_addrs, subject, message_body):
if TESTS_ENABLED:
EMAIL_TEST_INBOX.append(message)
- elif mgoblin_globals.email_debug_mode:
+ if getattr(mgoblin_globals, 'email_debug_mode', False):
print u"===== Email ====="
print u"From address: %s" % message['From']
print u"To addresses: %s" % message['To']
@@ -180,6 +180,4 @@ def send_email(from_addr, to_addrs, subject, message_body):
print u"-- Body: --"
print message.get_payload(decode=True)
- else:
- return mhost.sendmail(from_addr, to_addrs, message.as_string())
-
+ return mhost.sendmail(from_addr, to_addrs, message.as_string())
--
cgit v1.2.3
From 8b28bee4c1de6f1190091f5c17c0cf0f948c7071 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 14:57:58 -0500
Subject: Added some locale determination tools
---
mediagoblin/tests/test_util.py | 26 ++++++++++++++++++++
mediagoblin/util.py | 56 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 82 insertions(+)
diff --git a/mediagoblin/tests/test_util.py b/mediagoblin/tests/test_util.py
index 5bc31fd6..ff40a677 100644
--- a/mediagoblin/tests/test_util.py
+++ b/mediagoblin/tests/test_util.py
@@ -69,3 +69,29 @@ I hope you like unit tests JUST AS MUCH AS I DO!"""
assert mbox_message.get_payload(decode=True) == """HAYYY GUYS!
I hope you like unit tests JUST AS MUCH AS I DO!"""
+
+
+def test_locale_to_lower_upper():
+ """
+ Test cc.i18n.util.locale_to_lower_upper()
+ """
+ assert util.locale_to_lower_upper('en') == 'en'
+ assert util.locale_to_lower_upper('en_US') == 'en_US'
+ assert util.locale_to_lower_upper('en-us') == 'en_US'
+
+ # crazy renditions. Useful?
+ assert util.locale_to_lower_upper('en-US') == 'en_US'
+ assert util.locale_to_lower_upper('en_us') == 'en_US'
+
+
+def test_locale_to_lower_lower():
+ """
+ Test cc.i18n.util.locale_to_lower_lower()
+ """
+ assert util.locale_to_lower_lower('en') == 'en'
+ assert util.locale_to_lower_lower('en_US') == 'en-us'
+ assert util.locale_to_lower_lower('en-us') == 'en-us'
+
+ # crazy renditions. Useful?
+ assert util.locale_to_lower_lower('en-US') == 'en-us'
+ assert util.locale_to_lower_lower('en_us') == 'en-us'
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index 63f0f9c5..2b7948c8 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -183,3 +183,59 @@ def send_email(from_addr, to_addrs, subject, message_body):
else:
return mhost.sendmail(from_addr, to_addrs, message.as_string())
+
+###################
+# Translation tools
+###################
+
+
+def locale_to_lower_upper(locale):
+ """
+ Take a locale, regardless of style, and format it like "en-us"
+ """
+ if '-' in locale:
+ lang, country = locale.split('-', 1)
+ return '%s_%s' % (lang.lower(), country.upper())
+ elif '_' in locale:
+ lang, country = locale.split('_', 1)
+ return '%s_%s' % (lang.lower(), country.upper())
+ else:
+ return locale.lower()
+
+
+def locale_to_lower_lower(locale):
+ """
+ Take a locale, regardless of style, and format it like "en_US"
+ """
+ if '_' in locale:
+ lang, country = locale.split('_', 1)
+ return '%s-%s' % (lang.lower(), country.lower())
+ else:
+ return locale.lower()
+
+
+def get_locale_from_request(request):
+ """
+ Figure out what target language is most appropriate based on the
+ request
+ """
+ request_form = request.GET or request.POST
+
+ if request_form.has_key('lang'):
+ return locale_to_lower_upper(request_form['lang'])
+
+ accept_lang_matches = request.accept_language.best_matches()
+
+ # Your routing can explicitly specify a target language
+ if request.matchdict.has_key('target_lang'):
+ target_lang = request.matchdict['target_lang']
+ elif request.session.has_key('target_lang'):
+ target_lang = request.session['target_lang']
+ # Pull the first acceptable language
+ elif accept_lang_matches:
+ target_lang = accept_lang_matches[0]
+ # Fall back to English
+ else:
+ target_lang = 'en'
+
+ return make_locale_lower_upper_style(target_lang)
--
cgit v1.2.3
From 0e0e3d9aadd481353c9a4a44b37dcb68c1efbaab Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 15:17:07 -0500
Subject: Separation between setting up the template env and the template
loader for a glorious future where we have gettext in template context
---
mediagoblin/app.py | 7 +++++--
mediagoblin/util.py | 20 ++++++++++++++------
2 files changed, 19 insertions(+), 8 deletions(-)
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index 2a2f21cc..d124558d 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -40,7 +40,7 @@ class MediaGoblinApp(object):
email_sender_address, email_debug_mode,
user_template_path=None):
# Get the template environment
- self.template_env = util.get_jinja_env(user_template_path)
+ self.template_loader = util.get_jinja_loader(user_template_path)
# Set up storage systems
self.public_store = public_store
@@ -103,7 +103,10 @@ class MediaGoblinApp(object):
# Attach self as request.app
# Also attach a few utilities from request.app for convenience?
request.app = self
- request.template_env = self.template_env
+ request.locale = util.get_locale_from_request(request)
+
+ request.template_env = util.get_jinja_env(
+ self.template_loader, request.locale)
request.db = self.db
request.staticdirect = self.staticdirector
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index f02b5f51..ac977bdb 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -33,23 +33,31 @@ def _activate_testing():
TESTS_ENABLED = True
-def get_jinja_env(user_template_path=None):
+def get_jinja_loader(user_template_path=None):
"""
- Set up the Jinja environment, possibly allowing for user
+ Set up the Jinja template loaders, possibly allowing for user
overridden templates.
(In the future we may have another system for providing theming;
for now this is good enough.)
"""
if user_template_path:
- loader = jinja2.ChoiceLoader(
+ return jinja2.ChoiceLoader(
[jinja2.FileSystemLoader(user_template_path),
jinja2.PackageLoader('mediagoblin', 'templates')])
else:
- loader = jinja2.PackageLoader('mediagoblin', 'templates')
+ return jinja2.PackageLoader('mediagoblin', 'templates')
+
+def get_jinja_env(template_loader, locale):
+ """
+ Set up the Jinja environment,
+
+ (In the future we may have another system for providing theming;
+ for now this is good enough.)
+ """
return jinja2.Environment(
- loader=loader, autoescape=True,
+ loader=template_loader, autoescape=True,
extensions=['jinja2.ext.i18n'])
@@ -237,4 +245,4 @@ def get_locale_from_request(request):
else:
target_lang = 'en'
- return make_locale_lower_upper_style(target_lang)
+ return locale_to_lower_upper(target_lang)
--
cgit v1.2.3
From e461b7771300ab75777b01f4732fdcbc358064f7 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 15:26:15 -0500
Subject: moving mediagoblin.po to a filename that makes sense
---
.../translations/en/LC_MESSAGES/mediagoblin.po | 23 ++++++++++++++++++++++
mediagoblin/translations/master.po | 23 ----------------------
2 files changed, 23 insertions(+), 23 deletions(-)
create mode 100644 mediagoblin/translations/en/LC_MESSAGES/mediagoblin.po
delete mode 100644 mediagoblin/translations/master.po
diff --git a/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.po b/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.po
new file mode 100644
index 00000000..0e242fee
--- /dev/null
+++ b/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.po
@@ -0,0 +1,23 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+# FIRST AUTHOR , 2011.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2011-05-12 10:17-0500\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+
+#: mediagoblin/templates/mediagoblin/root.html:21
+msgid "Welcome to GNU MediaGoblin!"
+msgstr ""
+
diff --git a/mediagoblin/translations/master.po b/mediagoblin/translations/master.po
deleted file mode 100644
index 0e242fee..00000000
--- a/mediagoblin/translations/master.po
+++ /dev/null
@@ -1,23 +0,0 @@
-# Translations template for PROJECT.
-# Copyright (C) 2011 ORGANIZATION
-# This file is distributed under the same license as the PROJECT project.
-# FIRST AUTHOR , 2011.
-#
-#, fuzzy
-msgid ""
-msgstr ""
-"Project-Id-Version: PROJECT VERSION\n"
-"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2011-05-12 10:17-0500\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
-"Last-Translator: FULL NAME \n"
-"Language-Team: LANGUAGE \n"
-"MIME-Version: 1.0\n"
-"Content-Type: text/plain; charset=utf-8\n"
-"Content-Transfer-Encoding: 8bit\n"
-"Generated-By: Babel 0.9.6\n"
-
-#: mediagoblin/templates/mediagoblin/root.html:21
-msgid "Welcome to GNU MediaGoblin!"
-msgstr ""
-
--
cgit v1.2.3
From b77eec653df14059296fc3185ff9817edfa0825b Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 22:33:30 -0500
Subject: Load gettext, and load it into the template environment
---
mediagoblin/globals.py | 9 ++++++
mediagoblin/templates/mediagoblin/root.html | 4 +--
.../translations/en/LC_MESSAGES/mediagoblin.mo | Bin 0 -> 502 bytes
.../translations/en/LC_MESSAGES/mediagoblin.po | 4 +--
mediagoblin/util.py | 33 ++++++++++++++++++++-
5 files changed, 44 insertions(+), 6 deletions(-)
create mode 100644 mediagoblin/translations/en/LC_MESSAGES/mediagoblin.mo
diff --git a/mediagoblin/globals.py b/mediagoblin/globals.py
index 59a94558..80d1f01d 100644
--- a/mediagoblin/globals.py
+++ b/mediagoblin/globals.py
@@ -2,6 +2,9 @@
In some places, we need to access the database, public_store, queue_store
"""
+import gettext
+import pkg_resources
+
#############################
# General mediagoblin globals
#############################
@@ -16,6 +19,12 @@ database = None
public_store = None
queue_store = None
+# gettext
+translations = gettext.find(
+ 'mediagoblin',
+ pkg_resources.resource_filename(
+ 'mediagoblin', 'translations'), ['en'])
+
def setup_globals(**kwargs):
from mediagoblin import globals as mg_globals
diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html
index 44d26a65..fa78bda2 100644
--- a/mediagoblin/templates/mediagoblin/root.html
+++ b/mediagoblin/templates/mediagoblin/root.html
@@ -19,9 +19,7 @@
{% block mediagoblin_content %}
-
Welcome to GNU MediaGoblin!
- {#
-
{% trans %}Welcome to GNU MediaGoblin!{% endtrans %}
#}
+
{% trans %}Welcome to GNU MediaGoblin!{% endtrans %}
{% if request.user %}
diff --git a/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.mo b/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.mo
new file mode 100644
index 00000000..fb7046cd
Binary files /dev/null and b/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.mo differ
diff --git a/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.po b/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.po
index 0e242fee..3bec204e 100644
--- a/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.po
+++ b/mediagoblin/translations/en/LC_MESSAGES/mediagoblin.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2011-05-12 10:17-0500\n"
+"POT-Creation-Date: 2011-05-12 22:28-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 0.9.6\n"
-#: mediagoblin/templates/mediagoblin/root.html:21
+#: mediagoblin/templates/mediagoblin/root.html:22
msgid "Welcome to GNU MediaGoblin!"
msgstr ""
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index ac977bdb..8c6ec6cc 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -15,6 +15,8 @@
# along with this program. If not, see .
from email.MIMEText import MIMEText
+import gettext
+import pkg_resources
import smtplib
import sys
@@ -56,10 +58,18 @@ def get_jinja_env(template_loader, locale):
(In the future we may have another system for providing theming;
for now this is good enough.)
"""
- return jinja2.Environment(
+ setup_gettext(locale)
+
+ template_env = jinja2.Environment(
loader=template_loader, autoescape=True,
extensions=['jinja2.ext.i18n'])
+ template_env.install_gettext_callables(
+ mgoblin_globals.translations.gettext,
+ mgoblin_globals.translations.ngettext)
+
+ return template_env
+
def setup_user_in_request(request):
"""
@@ -196,6 +206,10 @@ def send_email(from_addr, to_addrs, subject, message_body):
###################
+TRANSLATIONS_PATH = pkg_resources.resource_filename(
+ 'mediagoblin', 'translations')
+
+
def locale_to_lower_upper(locale):
"""
Take a locale, regardless of style, and format it like "en-us"
@@ -246,3 +260,20 @@ def get_locale_from_request(request):
target_lang = 'en'
return locale_to_lower_upper(target_lang)
+
+
+def setup_gettext(locale):
+ """
+ Setup the gettext instance based on this locale
+ """
+ # Later on when we have plugins we may want to enable the
+ # multi-translations system they have so we can handle plugin
+ # translations too
+
+ # TODO: fallback nicely on translations from pt_PT to pt if not
+ # available, etc.
+ this_gettext = gettext.translation(
+ 'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
+
+ mgoblin_globals.setup_globals(
+ translations=this_gettext)
--
cgit v1.2.3
From 7acdbfd36457720789c183260424e0f78139211a Mon Sep 17 00:00:00 2001
From: Sebastian Spaeth
Date: Wed, 11 May 2011 08:39:57 +0200
Subject: Improve user homepage
1) Only consider user's with 'status': 'active'. We don't want to
display unconfirmed/blocked users, right?
2) Actually query user's media in the view and display on their home
page.
3) Throw an error 404 if we don't find a valid user, rather than saying,
"User not found" (from within the template).
4) Pass in medias as media_entries to remain compatible with the 'root'
page.
Signed-off-by: Sebastian Spaeth
---
.../templates/mediagoblin/user_pages/user.html | 15 ++++++++++++-
mediagoblin/user_pages/views.py | 25 ++++++++++++++--------
2 files changed, 30 insertions(+), 10 deletions(-)
diff --git a/mediagoblin/templates/mediagoblin/user_pages/user.html b/mediagoblin/templates/mediagoblin/user_pages/user.html
index 4fa84430..85f05e08 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/user.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/user.html
@@ -19,8 +19,21 @@
{% block mediagoblin_content -%}
{% if user %}
User page for '{{ user.username }}'
- {{ user }}
+
+ {#- Should we outsource such a media 'gallery' view to it's own file?
+ It could be useful for the home page and other views too -#}
+
{% else %}
+ {# This *should* not occur as the view makes sure we pass in a user. #}
Sorry, no such user found.
{% endif %}
{% endblock %}
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index cc613c40..2c9792fa 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -14,17 +14,22 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-from webob import Response
+from webob import Response, exc
from mongokit import ObjectId
import wtforms
def user_home(request):
"""'Homepage' of a User()"""
- user = request.db.User.find_one(
- {'username': request.matchdict['user']})
+ user = request.db.User.find_one({
+ 'username': request.matchdict['user'],
+ 'status': 'active'})
+ if not user:
+ return exc.HTTPNotFound()
- medias = request.db.MediaEntry.find()
+ medias = request.db.MediaEntry.find({
+ 'uploader': user,
+ 'state': 'processed'})
template = request.template_env.get_template(
'mediagoblin/user_pages/user.html')
@@ -32,16 +37,18 @@ def user_home(request):
template.render(
{'request': request,
'user': user,
- 'medias': medias}))
+ 'media_entries': medias}))
def media_home(request):
"""'Homepage' of a MediaEntry()"""
- media = request.db.MediaEntry.find_one(
- ObjectId(request.matchdict['m_id']))
+ media = request.db.MediaEntry.find_one({
+ '_id': ObjectId(request.matchdict['m_id']),
+ 'state': 'processed'})
- #check that media uploader and user correspond
- if media['uploader'].get('username') != request.matchdict['user']:
+ # Check that media uploader and user correspond.
+ if not media or \
+ media['uploader'].get('username') != request.matchdict['user']:
return exc.HTTPNotFound()
template = request.template_env.get_template(
--
cgit v1.2.3
From 376e6ef296299570ed3e09fca50536bbbf48328a Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 23:17:53 -0500
Subject: locale rather than target_lang in the get parameters
---
mediagoblin/util.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index 8c6ec6cc..1f568ed3 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -248,8 +248,8 @@ def get_locale_from_request(request):
accept_lang_matches = request.accept_language.best_matches()
# Your routing can explicitly specify a target language
- if request.matchdict.has_key('target_lang'):
- target_lang = request.matchdict['target_lang']
+ if request.matchdict.has_key('locale'):
+ target_lang = request.matchdict['locale']
elif request.session.has_key('target_lang'):
target_lang = request.session['target_lang']
# Pull the first acceptable language
--
cgit v1.2.3
From bb49e56f8c855ea567d61ad63f93610b31d4eb27 Mon Sep 17 00:00:00 2001
From: Aaron Williamson
Date: Mon, 9 May 2011 00:06:38 -0400
Subject: On image submission, do not require title. If none entered, default
to filename.
---
mediagoblin/models.py | 2 +-
mediagoblin/submit/forms.py | 2 +-
mediagoblin/submit/views.py | 8 +++++---
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/mediagoblin/models.py b/mediagoblin/models.py
index 69b1f4f0..5b286038 100644
--- a/mediagoblin/models.py
+++ b/mediagoblin/models.py
@@ -89,7 +89,7 @@ class MediaEntry(Document):
'thumbnail_file': [unicode]}
required_fields = [
- 'uploader', 'title', 'created', 'media_type']
+ 'uploader', 'created', 'media_type']
default_values = {
'created': datetime.datetime.utcnow,
diff --git a/mediagoblin/submit/forms.py b/mediagoblin/submit/forms.py
index fe51e7fd..51ca349d 100644
--- a/mediagoblin/submit/forms.py
+++ b/mediagoblin/submit/forms.py
@@ -21,6 +21,6 @@ import wtforms
class SubmitStartForm(wtforms.Form):
title = wtforms.TextField(
'Title',
- [wtforms.validators.Length(min=1, max=500)])
+ [wtforms.validators.Length(min=-1, max=500)])
description = wtforms.TextAreaField('Description of this work')
file = wtforms.FileField('File')
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 5e262f12..1b28e339 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -14,7 +14,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-
+from os.path import splitext
from cgi import FieldStorage
from webob import Response, exc
@@ -39,9 +39,11 @@ def submit_start(request):
submit_form.file.errors.append(
u'You must provide a file.')
else:
+ filename = request.POST['file'].filename
+
# create entry and save in database
entry = request.db.MediaEntry()
- entry['title'] = request.POST['title']
+ entry['title'] = request.POST['title'] or unicode(splitext(filename)[0])
entry['description'] = request.POST.get('description')
entry['media_type'] = u'image' # heh
entry['uploader'] = request.user
@@ -54,7 +56,7 @@ def submit_start(request):
queue_filepath = request.app.queue_store.get_unique_filepath(
['media_entries',
unicode(entry['_id']),
- secure_filename(request.POST['file'].filename)])
+ secure_filename(filename)])
# queue appropriately
queue_file = request.app.queue_store.get_file(
--
cgit v1.2.3
From a8e2812b054f49e4085bf6b8c0b9e0c5f1b8d312 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 12 May 2011 23:40:47 -0500
Subject: min=0 makes more sense than min=-1
---
mediagoblin/submit/forms.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/submit/forms.py b/mediagoblin/submit/forms.py
index 51ca349d..3fd9ea49 100644
--- a/mediagoblin/submit/forms.py
+++ b/mediagoblin/submit/forms.py
@@ -21,6 +21,6 @@ import wtforms
class SubmitStartForm(wtforms.Form):
title = wtforms.TextField(
'Title',
- [wtforms.validators.Length(min=-1, max=500)])
+ [wtforms.validators.Length(min=0, max=500)])
description = wtforms.TextAreaField('Description of this work')
file = wtforms.FileField('File')
--
cgit v1.2.3
From 0546833c6ea4dcaaa82861819916760dd62d8fa7 Mon Sep 17 00:00:00 2001
From: Aaron Williamson
Date: Fri, 13 May 2011 12:18:52 -0400
Subject: Generate unique slugs for newly submitted images.
---
mediagoblin/models.py | 11 ++++++++++-
mediagoblin/submit/views.py | 3 +++
mediagoblin/tests/test_util.py | 8 ++++++++
mediagoblin/util.py | 15 ++++++++++++++-
mediagoblin/views.py | 1 +
setup.py | 1 +
6 files changed, 37 insertions(+), 2 deletions(-)
diff --git a/mediagoblin/models.py b/mediagoblin/models.py
index 5b286038..1ecabe3e 100644
--- a/mediagoblin/models.py
+++ b/mediagoblin/models.py
@@ -18,8 +18,9 @@ import datetime, uuid
from mongokit import Document, Set
+from mediagoblin import util
from mediagoblin.auth import lib as auth_lib
-
+from mediagoblin import globals as mediagoblin_globals
###################
# Custom validators
@@ -66,6 +67,7 @@ class MediaEntry(Document):
structure = {
'uploader': User,
'title': unicode,
+ 'slug':unicode,
'created': datetime.datetime,
'description': unicode,
'media_type': unicode,
@@ -98,6 +100,13 @@ class MediaEntry(Document):
def main_mediafile(self):
pass
+ def generate_slug(self):
+ self['slug'] = util.slugify(self['title'])
+
+ duplicate = mediagoblin_globals.database.media_entries.find_one({'slug': self['slug']})
+
+ if duplicate:
+ self['slug'] = "%s-%s" % (self['_id'], self['slug'])
REGISTER_MODELS = [MediaEntry, User]
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 1b28e339..95a416e2 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -52,6 +52,9 @@ def submit_start(request):
# it to generate the file path
entry.save(validate=False)
+ # Generate a slug from the title
+ entry.generate_slug()
+
# Now store generate the queueing related filename
queue_filepath = request.app.queue_store.get_unique_filepath(
['media_entries',
diff --git a/mediagoblin/tests/test_util.py b/mediagoblin/tests/test_util.py
index ff40a677..7b00a074 100644
--- a/mediagoblin/tests/test_util.py
+++ b/mediagoblin/tests/test_util.py
@@ -70,6 +70,14 @@ I hope you like unit tests JUST AS MUCH AS I DO!"""
I hope you like unit tests JUST AS MUCH AS I DO!"""
+def test_slugify():
+ assert util.slugify('a walk in the park') == 'a-walk-in-the-park'
+ assert util.slugify('A Walk in the Park') == 'a-walk-in-the-park'
+ assert util.slugify('a walk in the park') == 'a-walk-in-the-park'
+ assert util.slugify('a walk in-the-park') == 'a-walk-in-the-park'
+ assert util.slugify('a w@lk in the park?') == 'a-w-lk-in-the-park'
+ assert util.slugify(u'a walk in the par\u0107') == 'a-walk-in-the-parc'
+ assert util.slugify(u'\u00E0\u0042\u00E7\u010F\u00EB\u0066') == 'abcdef'
def test_locale_to_lower_upper():
"""
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index 1f568ed3..a66e2ba5 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -19,9 +19,10 @@ import gettext
import pkg_resources
import smtplib
import sys
-
+import re
import jinja2
import mongokit
+import translitcodec
from mediagoblin import globals as mgoblin_globals
@@ -107,6 +108,18 @@ def import_component(import_string):
func = getattr(module, func_name)
return func
+_punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.]+')
+
+def slugify(text, delim=u'-'):
+ """
+ Generates an ASCII-only slug. Taken from http://flask.pocoo.org/snippets/5/
+ """
+ result = []
+ for word in _punct_re.split(text.lower()):
+ word = word.encode('translit/long')
+ if word:
+ result.append(word)
+ return unicode(delim.join(result))
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### Special email test stuff begins HERE
diff --git a/mediagoblin/views.py b/mediagoblin/views.py
index 95d0be7a..7f925bb7 100644
--- a/mediagoblin/views.py
+++ b/mediagoblin/views.py
@@ -20,6 +20,7 @@ from webob import Response, exc
import wtforms
from mongokit import ObjectId
from mediagoblin import models
+import gettext
def root_view(request):
media_entries = request.db.MediaEntry.find(
diff --git a/setup.py b/setup.py
index 7d38e526..08887dee 100644
--- a/setup.py
+++ b/setup.py
@@ -39,6 +39,7 @@ setup(
'sphinx',
'PIL',
'Babel',
+ 'translitcodec',
],
test_suite='nose.collector',
--
cgit v1.2.3
From 1013bdaff2f3ab4bb67667b57470d23cf392a3df Mon Sep 17 00:00:00 2001
From: Aaron Williamson
Date: Fri, 13 May 2011 14:16:35 -0400
Subject: Minor fomatting fix.
---
mediagoblin/models.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/models.py b/mediagoblin/models.py
index 1ecabe3e..4a867323 100644
--- a/mediagoblin/models.py
+++ b/mediagoblin/models.py
@@ -67,7 +67,7 @@ class MediaEntry(Document):
structure = {
'uploader': User,
'title': unicode,
- 'slug':unicode,
+ 'slug': unicode,
'created': datetime.datetime,
'description': unicode,
'media_type': unicode,
--
cgit v1.2.3
From 881b6e2c32d8013d6ffaa151fd1b7d78041fed60 Mon Sep 17 00:00:00 2001
From: Jef van Schendel
Date: Fri, 13 May 2011 15:33:19 -0500
Subject: Fixing changes
---
mediagoblin/static/css/base.css | 71 +++++++++++++++++++-
mediagoblin/static/css/base.css~ | 70 ++++++++++++++++++++
mediagoblin/static/images/back.png | Bin 0 -> 26165 bytes
mediagoblin/static/images/button_green.png | Bin 0 -> 2054 bytes
mediagoblin/static/images/button_red.png | Bin 0 -> 1737 bytes
mediagoblin/static/images/header_back.png | Bin 0 -> 26226 bytes
mediagoblin/static/images/logo.png | Bin 0 -> 58408 bytes
mediagoblin/templates/mediagoblin/base.html | 5 +-
mediagoblin/templates/mediagoblin/base.html~ | 72 +++++++++++++++++++++
.../templates/mediagoblin/media_details.html | 2 +-
.../templates/mediagoblin/media_details.html~ | 34 ++++++++++
mediagoblin/templates/mediagoblin/root.html | 2 +-
mediagoblin/templates/mediagoblin/root.html~ | 56 ++++++++++++++++
13 files changed, 307 insertions(+), 5 deletions(-)
create mode 100644 mediagoblin/static/css/base.css~
create mode 100644 mediagoblin/static/images/back.png
create mode 100644 mediagoblin/static/images/button_green.png
create mode 100644 mediagoblin/static/images/button_red.png
create mode 100644 mediagoblin/static/images/header_back.png
create mode 100644 mediagoblin/static/images/logo.png
create mode 100644 mediagoblin/templates/mediagoblin/base.html~
create mode 100644 mediagoblin/templates/mediagoblin/media_details.html~
create mode 100644 mediagoblin/templates/mediagoblin/root.html~
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index 93b0b1a2..17f9e012 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -1 +1,70 @@
-/* stuff goes here :) */
\ No newline at end of file
+body {
+ background-color: #272727;
+ background-image: url('back.png');
+ color: #f7f7f7;
+ font-family: sans;
+ padding:none;
+ margin:0px;
+}
+
+h1 {
+ font-family: 'Carter One', arial, serif;
+ margin-bottom: 20px;
+ margin-top:50px;
+}
+
+.dottedLine {
+ width:100%;
+ height:0px;
+ border-bottom: dotted 1px #5f5f5f;
+ position:absolute;
+ left:0px;
+ margin-top:-20px;
+}
+
+a {
+ color: #d12929;
+ border-bottom: 1px dotted;
+ text-decoration: none;
+}
+
+.header {
+ width:100%;
+ height:60px;
+ background-image:url('header_back.png');
+ padding-top:40px;
+ margin-bottom:80px;
+}
+
+.container {
+ width: 800px;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.button {
+ font-family: 'Carter One', arial, serif;
+ height: 28px;
+ min-width: 99px;
+ box-shadow: 0px 0px 5px #000;
+ border-radius: 5px;
+ border: none;
+ color: #272727;
+ margin: 10px;
+ font-size: 1em;
+ float: left;
+ display: block;
+ text-align: center;
+ padding-top: 4px;
+ padding-left:11px;
+ padding-right:11px;
+}
+
+.buttonRed {
+ background-image: url('button_red.png');
+}
+
+.buttonGreen {
+ background-image: url('button_green.png');
+}
+
diff --git a/mediagoblin/static/css/base.css~ b/mediagoblin/static/css/base.css~
new file mode 100644
index 00000000..17f9e012
--- /dev/null
+++ b/mediagoblin/static/css/base.css~
@@ -0,0 +1,70 @@
+body {
+ background-color: #272727;
+ background-image: url('back.png');
+ color: #f7f7f7;
+ font-family: sans;
+ padding:none;
+ margin:0px;
+}
+
+h1 {
+ font-family: 'Carter One', arial, serif;
+ margin-bottom: 20px;
+ margin-top:50px;
+}
+
+.dottedLine {
+ width:100%;
+ height:0px;
+ border-bottom: dotted 1px #5f5f5f;
+ position:absolute;
+ left:0px;
+ margin-top:-20px;
+}
+
+a {
+ color: #d12929;
+ border-bottom: 1px dotted;
+ text-decoration: none;
+}
+
+.header {
+ width:100%;
+ height:60px;
+ background-image:url('header_back.png');
+ padding-top:40px;
+ margin-bottom:80px;
+}
+
+.container {
+ width: 800px;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.button {
+ font-family: 'Carter One', arial, serif;
+ height: 28px;
+ min-width: 99px;
+ box-shadow: 0px 0px 5px #000;
+ border-radius: 5px;
+ border: none;
+ color: #272727;
+ margin: 10px;
+ font-size: 1em;
+ float: left;
+ display: block;
+ text-align: center;
+ padding-top: 4px;
+ padding-left:11px;
+ padding-right:11px;
+}
+
+.buttonRed {
+ background-image: url('button_red.png');
+}
+
+.buttonGreen {
+ background-image: url('button_green.png');
+}
+
diff --git a/mediagoblin/static/images/back.png b/mediagoblin/static/images/back.png
new file mode 100644
index 00000000..3d7fe844
Binary files /dev/null and b/mediagoblin/static/images/back.png differ
diff --git a/mediagoblin/static/images/button_green.png b/mediagoblin/static/images/button_green.png
new file mode 100644
index 00000000..0fc234d4
Binary files /dev/null and b/mediagoblin/static/images/button_green.png differ
diff --git a/mediagoblin/static/images/button_red.png b/mediagoblin/static/images/button_red.png
new file mode 100644
index 00000000..b0f7dcad
Binary files /dev/null and b/mediagoblin/static/images/button_red.png differ
diff --git a/mediagoblin/static/images/header_back.png b/mediagoblin/static/images/header_back.png
new file mode 100644
index 00000000..3647b99d
Binary files /dev/null and b/mediagoblin/static/images/header_back.png differ
diff --git a/mediagoblin/static/images/logo.png b/mediagoblin/static/images/logo.png
new file mode 100644
index 00000000..8d2f6272
Binary files /dev/null and b/mediagoblin/static/images/logo.png differ
diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html
index 71c2e550..07be3c47 100644
--- a/mediagoblin/templates/mediagoblin/base.html
+++ b/mediagoblin/templates/mediagoblin/base.html
@@ -23,7 +23,8 @@
-
+
GNU MediaGoblin at your duty!
+
diff --git a/mediagoblin/templates/mediagoblin/base.html~ b/mediagoblin/templates/mediagoblin/base.html~
new file mode 100644
index 00000000..07be3c47
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/base.html~
@@ -0,0 +1,72 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+
+
+ {% block title %}MediaGoblin{% endblock title %}
+
+
+
+
+
GNU MediaGoblin at your duty!
+
+
+
diff --git a/mediagoblin/templates/mediagoblin/media_details.html b/mediagoblin/templates/mediagoblin/media_details.html
index 1b02c809..bd63a289 100644
--- a/mediagoblin/templates/mediagoblin/media_details.html
+++ b/mediagoblin/templates/mediagoblin/media_details.html
@@ -20,7 +20,7 @@
{# temporarily, an "image gallery" that isn't one really ;) #}
{% if media %}
-
Media details for {{media.title}}
+
Media details for {{media.title}}
diff --git a/mediagoblin/templates/mediagoblin/media_details.html~ b/mediagoblin/templates/mediagoblin/media_details.html~
new file mode 100644
index 00000000..1b02c809
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/media_details.html~
@@ -0,0 +1,34 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+{% block mediagoblin_content %}
+
+ {# temporarily, an "image gallery" that isn't one really ;) #}
+ {% if media %}
+
{% trans %}Welcome to GNU MediaGoblin!{% endtrans %}
+
{% trans %}Welcome to GNU MediaGoblin!{% endtrans %}
{% if request.user %}
diff --git a/mediagoblin/templates/mediagoblin/root.html~ b/mediagoblin/templates/mediagoblin/root.html~
new file mode 100644
index 00000000..fa78bda2
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/root.html~
@@ -0,0 +1,56 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% block mediagoblin_content %}
+
+
{% trans %}Welcome to GNU MediaGoblin!{% endtrans %}
+
+{% endblock %}
--
cgit v1.2.3
From 20aaec5f683ba23b0b4b18123367c2f93f2dd73d Mon Sep 17 00:00:00 2001
From: Jef van Schendel
Date: Fri, 13 May 2011 15:33:27 -0500
Subject: Changed base.html back to old version
---
mediagoblin/templates/mediagoblin/base.html | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html
index 07be3c47..d73d8c20 100644
--- a/mediagoblin/templates/mediagoblin/base.html
+++ b/mediagoblin/templates/mediagoblin/base.html
@@ -23,8 +23,6 @@
-
GNU MediaGoblin at your duty!
-
+ {% endblock mediagoblin_body %}
--
cgit v1.2.3
From 8c01ae42e9ed502c0a37bed2f449076aa183ec83 Mon Sep 17 00:00:00 2001
From: Jef van Schendel
Date: Fri, 13 May 2011 15:33:46 -0500
Subject: Styled input buttons
---
mediagoblin/templates/mediagoblin/auth/login.html | 2 +-
mediagoblin/templates/mediagoblin/auth/login.html~ | 44 ++++++++++++++++++++++
.../templates/mediagoblin/auth/register.html | 2 +-
.../templates/mediagoblin/auth/register.html~ | 33 ++++++++++++++++
mediagoblin/templates/mediagoblin/test_submit.html | 2 +-
.../templates/mediagoblin/test_submit.html~ | 33 ++++++++++++++++
6 files changed, 113 insertions(+), 3 deletions(-)
create mode 100644 mediagoblin/templates/mediagoblin/auth/login.html~
create mode 100644 mediagoblin/templates/mediagoblin/auth/register.html~
create mode 100644 mediagoblin/templates/mediagoblin/test_submit.html~
diff --git a/mediagoblin/templates/mediagoblin/auth/login.html b/mediagoblin/templates/mediagoblin/auth/login.html
index f2e7b664..46552a39 100644
--- a/mediagoblin/templates/mediagoblin/auth/login.html
+++ b/mediagoblin/templates/mediagoblin/auth/login.html
@@ -38,7 +38,7 @@
{% if next %}
-
+
{% endif %}
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/auth/login.html~ b/mediagoblin/templates/mediagoblin/auth/login.html~
new file mode 100644
index 00000000..f2e7b664
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/auth/login.html~
@@ -0,0 +1,44 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+
+{% block mediagoblin_content %}
+
diff --git a/mediagoblin/templates/mediagoblin/auth/register.html~ b/mediagoblin/templates/mediagoblin/auth/register.html~
new file mode 100644
index 00000000..f3489397
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/auth/register.html~
@@ -0,0 +1,33 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+
+{% block mediagoblin_content %}
+
diff --git a/mediagoblin/templates/mediagoblin/test_submit.html~ b/mediagoblin/templates/mediagoblin/test_submit.html~
new file mode 100644
index 00000000..ebf93b59
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/test_submit.html~
@@ -0,0 +1,33 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+
+
+
+
diff --git a/mediagoblin/templates/mediagoblin/submit/start.html~ b/mediagoblin/templates/mediagoblin/submit/start.html~
new file mode 100644
index 00000000..562d9050
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/submit/start.html~
@@ -0,0 +1,35 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+
+{% block mediagoblin_content %}
+
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html~ b/mediagoblin/templates/mediagoblin/user_pages/media.html~
new file mode 100644
index 00000000..08cc9251
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html~
@@ -0,0 +1,41 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+{% block mediagoblin_content %}
+
+ {# temporarily, an "image gallery" that isn't one really ;) #}
+ {% if media %}
+
{#- Should we outsource such a media 'gallery' view to it's own file?
It could be useful for the home page and other views too -#}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/user.html~ b/mediagoblin/templates/mediagoblin/user_pages/user.html~
new file mode 100644
index 00000000..4ae7986e
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/user_pages/user.html~
@@ -0,0 +1,39 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+{% block mediagoblin_content -%}
+ {% if user %}
+
User page for '{{ user.username }}'
+
+ {#- Should we outsource such a media 'gallery' view to it's own file?
+ It could be useful for the home page and other views too -#}
+
--
cgit v1.2.3
From cb1e4a3d1f04ef9e7df47ec9ee6b075f264f57d6 Mon Sep 17 00:00:00 2001
From: Jef van Schendel
Date: Fri, 13 May 2011 15:34:35 -0500
Subject: Added @font-face to css
---
mediagoblin/static/css/base.css | 11 +++++++++++
mediagoblin/static/css/base.css~ | 11 +++++++++++
2 files changed, 22 insertions(+)
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index 3b6abd3e..169394d0 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -7,6 +7,17 @@ body {
margin:0px;
}
+/* Carter One font */
+
+@font-face {
+ font-family: 'Carter One';
+ font-style: normal;
+ font-weight: normal;
+ src: local('CarterOne'), url('http://themes.googleusercontent.com/font?kit=VjW2qt1pkqVtO22ObxgEBRsxEYwM7FgeyaSgU71cLG0') format('woff');
+}
+
+/* text styles */
+
h1 {
font-family: 'Carter One', arial, serif;
margin-bottom: 20px;
diff --git a/mediagoblin/static/css/base.css~ b/mediagoblin/static/css/base.css~
index 3b6abd3e..169394d0 100644
--- a/mediagoblin/static/css/base.css~
+++ b/mediagoblin/static/css/base.css~
@@ -7,6 +7,17 @@ body {
margin:0px;
}
+/* Carter One font */
+
+@font-face {
+ font-family: 'Carter One';
+ font-style: normal;
+ font-weight: normal;
+ src: local('CarterOne'), url('http://themes.googleusercontent.com/font?kit=VjW2qt1pkqVtO22ObxgEBRsxEYwM7FgeyaSgU71cLG0') format('woff');
+}
+
+/* text styles */
+
h1 {
font-family: 'Carter One', arial, serif;
margin-bottom: 20px;
--
cgit v1.2.3
From 983aa712ad6be83267016de7d10a3e9b027cb1b7 Mon Sep 17 00:00:00 2001
From: Jef van Schendel
Date: Fri, 13 May 2011 15:34:44 -0500
Subject: labels changed to font-weight normal instead of bold, css structure
improved
---
mediagoblin/static/css/base.css | 26 +++++++++++++++++---------
mediagoblin/static/css/base.css~ | 4 ++++
2 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index 169394d0..6c50377f 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -24,21 +24,18 @@ h1 {
margin-top:50px;
}
-.dotted_line {
- width:100%;
- height:0px;
- border-bottom: dotted 1px #5f5f5f;
- position:absolute;
- left:0px;
- margin-top:-20px;
-}
-
a {
color: #d12929;
border-bottom: 1px dotted;
text-decoration: none;
}
+label {
+ font-weight: normal;
+}
+
+/* website structure */
+
.mediagoblin_header {
width:100%;
height:60px;
@@ -71,6 +68,17 @@ a {
padding-right:11px;
}
+/* common website elements */
+
+.dotted_line {
+ width:100%;
+ height:0px;
+ border-bottom: dotted 1px #5f5f5f;
+ position:absolute;
+ left:0px;
+ margin-top:-20px;
+}
+
.button_red {
background-image: url('../images/button_red.png');
}
diff --git a/mediagoblin/static/css/base.css~ b/mediagoblin/static/css/base.css~
index 169394d0..4c5ae9ab 100644
--- a/mediagoblin/static/css/base.css~
+++ b/mediagoblin/static/css/base.css~
@@ -39,6 +39,10 @@ a {
text-decoration: none;
}
+label {
+ font-weight: normal;
+}
+
.mediagoblin_header {
width:100%;
height:60px;
--
cgit v1.2.3
From 9d4b435a728df8ad85cf2384eaf39be183322a03 Mon Sep 17 00:00:00 2001
From: Jef van Schendel
Date: Fri, 13 May 2011 15:38:04 -0500
Subject: Removing backup files and preventing them from showing up via
.gitignore
---
.gitignore | 3 +-
mediagoblin/templates/mediagoblin/auth/login.html~ | 44 -----------------
.../templates/mediagoblin/auth/register.html~ | 33 -------------
mediagoblin/templates/mediagoblin/base.html~ | 53 --------------------
.../templates/mediagoblin/media_details.html~ | 34 -------------
mediagoblin/templates/mediagoblin/root.html~ | 56 ----------------------
.../templates/mediagoblin/submit/start.html~ | 35 --------------
.../templates/mediagoblin/test_submit.html~ | 33 -------------
.../templates/mediagoblin/user_pages/media.html~ | 41 ----------------
.../templates/mediagoblin/user_pages/user.html~ | 39 ---------------
10 files changed, 2 insertions(+), 369 deletions(-)
delete mode 100644 mediagoblin/templates/mediagoblin/auth/login.html~
delete mode 100644 mediagoblin/templates/mediagoblin/auth/register.html~
delete mode 100644 mediagoblin/templates/mediagoblin/base.html~
delete mode 100644 mediagoblin/templates/mediagoblin/media_details.html~
delete mode 100644 mediagoblin/templates/mediagoblin/root.html~
delete mode 100644 mediagoblin/templates/mediagoblin/submit/start.html~
delete mode 100644 mediagoblin/templates/mediagoblin/test_submit.html~
delete mode 100644 mediagoblin/templates/mediagoblin/user_pages/media.html~
delete mode 100644 mediagoblin/templates/mediagoblin/user_pages/user.html~
diff --git a/.gitignore b/.gitignore
index 6f6fc624..9e01560a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,4 +10,5 @@ mediagoblin.egg-info
*.pyo
docs/_build/
user_dev/
-server-log.txt
\ No newline at end of file
+server-log.txt
+*~
\ No newline at end of file
diff --git a/mediagoblin/templates/mediagoblin/auth/login.html~ b/mediagoblin/templates/mediagoblin/auth/login.html~
deleted file mode 100644
index d5a5ddef..00000000
--- a/mediagoblin/templates/mediagoblin/auth/login.html~
+++ /dev/null
@@ -1,44 +0,0 @@
-{#
-# GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011 Free Software Foundation, Inc
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-#}
-{% extends "mediagoblin/base.html" %}
-
-{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
-
-{% block mediagoblin_content %}
-
Login:
-
-
-
- {% if login_failed %}
-
Login failed!
- {% endif %}
-
-
- {{ wtforms_util.render_table(login_form) }}
-
-
-
-
-
-
- {% if next %}
-
- {% endif %}
-
-{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/auth/register.html~ b/mediagoblin/templates/mediagoblin/auth/register.html~
deleted file mode 100644
index de3ec71d..00000000
--- a/mediagoblin/templates/mediagoblin/auth/register.html~
+++ /dev/null
@@ -1,33 +0,0 @@
-{#
-# GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011 Free Software Foundation, Inc
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-#}
-{% extends "mediagoblin/base.html" %}
-
-{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
-
-{% block mediagoblin_content %}
-
-{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/base.html~ b/mediagoblin/templates/mediagoblin/base.html~
deleted file mode 100644
index 4b634cf1..00000000
--- a/mediagoblin/templates/mediagoblin/base.html~
+++ /dev/null
@@ -1,53 +0,0 @@
-{#
-# GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011 Free Software Foundation, Inc
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-#}
-
-
- {% block title %}MediaGoblin{% endblock title %}
-
-
-
-
- {% block mediagoblin_body %}
- {% block mediagoblin_header %}
-
- {% endblock mediagoblin_body %}
-
-
diff --git a/mediagoblin/templates/mediagoblin/media_details.html~ b/mediagoblin/templates/mediagoblin/media_details.html~
deleted file mode 100644
index bd63a289..00000000
--- a/mediagoblin/templates/mediagoblin/media_details.html~
+++ /dev/null
@@ -1,34 +0,0 @@
-{#
-# GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011 Free Software Foundation, Inc
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-#}
-{% extends "mediagoblin/base.html" %}
-{% block mediagoblin_content %}
-
- {# temporarily, an "image gallery" that isn't one really ;) #}
- {% if media %}
-
- {% endif %}
-{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/root.html~ b/mediagoblin/templates/mediagoblin/root.html~
deleted file mode 100644
index e2b2730a..00000000
--- a/mediagoblin/templates/mediagoblin/root.html~
+++ /dev/null
@@ -1,56 +0,0 @@
-{#
-# GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011 Free Software Foundation, Inc
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-#}
-{% extends "mediagoblin/base.html" %}
-
-{% block mediagoblin_content %}
-
-
{% trans %}Welcome to GNU MediaGoblin!{% endtrans %}
-
-{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/submit/start.html~ b/mediagoblin/templates/mediagoblin/submit/start.html~
deleted file mode 100644
index 21a7ed4e..00000000
--- a/mediagoblin/templates/mediagoblin/submit/start.html~
+++ /dev/null
@@ -1,35 +0,0 @@
-{#
-# GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011 Free Software Foundation, Inc
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-#}
-{% extends "mediagoblin/base.html" %}
-
-{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
-
-{% block mediagoblin_content %}
-
Submit yer media
-
-
-
- {{ wtforms_util.render_table(submit_form) }}
-
-
-
-
-
-
-{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/test_submit.html~ b/mediagoblin/templates/mediagoblin/test_submit.html~
deleted file mode 100644
index ebf93b59..00000000
--- a/mediagoblin/templates/mediagoblin/test_submit.html~
+++ /dev/null
@@ -1,33 +0,0 @@
-{#
-# GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011 Free Software Foundation, Inc
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-#}
-{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
-
-
-
-
-
- {{ wtforms_util.render_table(image_form) }}
-
-
-
-
-
-
-
-
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html~ b/mediagoblin/templates/mediagoblin/user_pages/media.html~
deleted file mode 100644
index 08cc9251..00000000
--- a/mediagoblin/templates/mediagoblin/user_pages/media.html~
+++ /dev/null
@@ -1,41 +0,0 @@
-{#
-# GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011 Free Software Foundation, Inc
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-#}
-{% extends "mediagoblin/base.html" %}
-{% block mediagoblin_content %}
-
- {# temporarily, an "image gallery" that isn't one really ;) #}
- {% if media %}
-
-
-
- Uploaded on {{ "%4d-%02d-%02d"|format(media.created.year,
- media.created.month,media.created.day)}} by {{media.uploader.username}}
- Description: {{media.description}}
-
- {% else %}
-
Sorry, no such media found.
- {% endif %}
-{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/user.html~ b/mediagoblin/templates/mediagoblin/user_pages/user.html~
deleted file mode 100644
index 4ae7986e..00000000
--- a/mediagoblin/templates/mediagoblin/user_pages/user.html~
+++ /dev/null
@@ -1,39 +0,0 @@
-{#
-# GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011 Free Software Foundation, Inc
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-#}
-{% extends "mediagoblin/base.html" %}
-{% block mediagoblin_content -%}
- {% if user %}
-
User page for '{{ user.username }}'
-
- {#- Should we outsource such a media 'gallery' view to it's own file?
- It could be useful for the home page and other views too -#}
-
- {% else %}
- {# This *should* not occur as the view makes sure we pass in a user. #}
-
Sorry, no such user found.
- {% endif %}
-{% endblock %}
--
cgit v1.2.3
From e2decbcf1e0c9be461a5ee1ac40d3a7fe5492b36 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 13 May 2011 16:07:37 -0500
Subject: Removing the raw string-ness
---
mediagoblin/user_pages/routing.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py
index c2dc2fc0..304f805f 100644
--- a/mediagoblin/user_pages/routing.py
+++ b/mediagoblin/user_pages/routing.py
@@ -19,6 +19,6 @@ from routes.route import Route
user_routes = [
Route('mediagoblin.user_pages.user_home', "/{user}/",
controller="mediagoblin.user_pages.views:user_home"),
- Route('mediagoblin.user_pages.media_home', r'/{user}/m/{m_id}/',
+ Route('mediagoblin.user_pages.media_home', '/{user}/m/{m_id}/',
requirements=dict(m_id="[0-9a-fA-F]{24}"),
controller="mediagoblin.user_pages.views:media_home")]
--
cgit v1.2.3
From 029cad45c6fb61ac96b7601288a76523f98a247e Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 15 May 2011 19:02:11 -0500
Subject: ./bin/gmg shell! Should make a lot of peoples' hacking lives easier
I suspect :)
---
mediagoblin/gmg_commands/__init__.py | 106 +++++++++++++++++++++++++++++++++++
setup.py | 4 ++
2 files changed, 110 insertions(+)
create mode 100644 mediagoblin/gmg_commands/__init__.py
diff --git a/mediagoblin/gmg_commands/__init__.py b/mediagoblin/gmg_commands/__init__.py
new file mode 100644
index 00000000..04e2ab6c
--- /dev/null
+++ b/mediagoblin/gmg_commands/__init__.py
@@ -0,0 +1,106 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import code
+import argparse
+import os
+
+from paste.deploy.loadwsgi import NicerConfigParser
+
+from mediagoblin.celery_setup import setup_celery_from_config
+from mediagoblin import app, util
+from mediagoblin import globals as mgoblin_globals
+
+
+SUBCOMMAND_MAP = {
+ 'shell': {
+ 'setup': 'mediagoblin.gmg_commands:shell_parser_setup',
+ 'func': 'mediagoblin.gmg_commands:shell',
+ 'help': 'Run a shell with some tools pre-setup'},
+ }
+
+
+def shell_parser_setup(subparser):
+ subparser.add_argument(
+ '-cf', '--conf_file', default='mediagoblin.ini',
+ help="Config file used to set up environment")
+ subparser.add_argument(
+ '-cs', '--app_section', default='app:mediagoblin',
+ help="Section of the config file where the app config is stored.")
+
+
+SHELL_BANNER = """\
+GNU MediaGoblin shell!
+----------------------
+Available vars:
+ - mgoblin_app: instantiated mediagoblin application
+ - mgoblin_globals: mediagoblin.globals
+ - db: database instance
+"""
+
+
+def shell(args):
+ """
+ """
+ # Duplicated from from_celery.py, remove when we have the generic util
+ parser = NicerConfigParser(args.conf_file)
+ parser.read(args.conf_file)
+ parser._defaults.setdefault(
+ 'here', os.path.dirname(os.path.abspath(args.conf_file)))
+ parser._defaults.setdefault(
+ '__file__', os.path.abspath(args.conf_file))
+
+ mgoblin_section = dict(parser.items(args.app_section))
+ mgoblin_conf = dict(
+ [(section_name, dict(parser.items(section_name)))
+ for section_name in parser.sections()])
+
+ mgoblin_app = app.paste_app_factory(
+ mgoblin_conf, **mgoblin_section)
+
+ code.interact(
+ banner=SHELL_BANNER,
+ local={
+ 'mgoblin_app': mgoblin_app,
+ 'mgoblin_globals': mgoblin_globals,
+ 'db': mgoblin_globals.database})
+
+
+def main_cli():
+ parser = argparse.ArgumentParser(
+ description='GNU MediaGoblin utilities.')
+
+ subparsers = parser.add_subparsers(help='sub-command help')
+ for command_name, command_struct in SUBCOMMAND_MAP.iteritems():
+ if command_struct.has_key('help'):
+ subparser = subparsers.add_parser(
+ command_name, help=command_struct['help'])
+ else:
+ subparser = subparsers.add_parser(command_name)
+
+ setup_func = util.import_component(command_struct['setup'])
+ exec_func = util.import_component(command_struct['func'])
+
+ setup_func(subparser)
+
+ subparser.set_defaults(func=exec_func)
+
+ args = parser.parse_args()
+ args.func(args)
+
+
+if __name__ == '__main__':
+ main_cli()
diff --git a/setup.py b/setup.py
index 08887dee..752f1b57 100644
--- a/setup.py
+++ b/setup.py
@@ -40,6 +40,7 @@ setup(
'PIL',
'Babel',
'translitcodec',
+ 'argparse',
],
test_suite='nose.collector',
@@ -47,6 +48,9 @@ setup(
author = 'Christopher Webber',
author_email = 'cwebber@gnu.org',
entry_points = """\
+ [console_scripts]
+ gmg = mediagoblin.gmg_commands:main_cli
+
[paste.app_factory]
app = mediagoblin.app:paste_app_factory
--
cgit v1.2.3
From 400125148f82e0e67c70a25724d940d331063b44 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Mon, 16 May 2011 07:46:26 -0500
Subject: Properly linking to the background image
---
mediagoblin/static/css/base.css | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index 6c50377f..3a8d3cdc 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -1,6 +1,6 @@
body {
background-color: #272727;
- background-image: url('back.png');
+ background-image: url('../images/back.png');
color: #f7f7f7;
font-family: sans;
padding:none;
--
cgit v1.2.3
From 1ab8467320db7083bd651a26191cbecbdaa0f38d Mon Sep 17 00:00:00 2001
From: Sebastian Spaeth
Date: Mon, 16 May 2011 14:55:05 +0200
Subject: Show images in reverse submit order
Fixes bug #327. Just do a .sort('created', DESCENDING) on Media when
showing them to show the latest first.
Signed-off-by: Sebastian Spaeth
---
mediagoblin/user_pages/views.py | 3 ++-
mediagoblin/views.py | 3 ++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index 2c9792fa..c99556c2 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -15,6 +15,7 @@
# along with this program. If not, see .
from webob import Response, exc
+from pymongo import DESCENDING
from mongokit import ObjectId
import wtforms
@@ -29,7 +30,7 @@ def user_home(request):
medias = request.db.MediaEntry.find({
'uploader': user,
- 'state': 'processed'})
+ 'state': 'processed'}).sort('created', DESCENDING)
template = request.template_env.get_template(
'mediagoblin/user_pages/user.html')
diff --git a/mediagoblin/views.py b/mediagoblin/views.py
index 7f925bb7..602f1098 100644
--- a/mediagoblin/views.py
+++ b/mediagoblin/views.py
@@ -18,13 +18,14 @@ import datetime
from webob import Response, exc
import wtforms
+from pymongo import DESCENDING
from mongokit import ObjectId
from mediagoblin import models
import gettext
def root_view(request):
media_entries = request.db.MediaEntry.find(
- {u'state': u'processed'})
+ {u'state': u'processed'}).sort('created', DESCENDING)
template = request.template_env.get_template(
'mediagoblin/root.html')
--
cgit v1.2.3
From 3e4a2f2be7c4740f7192c18cf9d8c9cd9dfedad1 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Mon, 16 May 2011 17:35:56 -0500
Subject: ./bin/gmg shell documented in the hackinghowto
---
docs/hackinghowto.rst | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index b34ce93a..bf5278b3 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -249,6 +249,21 @@ If you did virtualenv, run::
nosetests
+Running a shell
+===============
+
+If you want a shell with your database pre-setup and an instantiated
+application ready and at your fingertips...
+
+If you did buildout, run::
+
+ ./bin/gmg shell
+
+If you did virtualenv, run::
+
+ gmg shell
+
+
Troubleshooting
===============
--
cgit v1.2.3
From 18cf34d4701f86f5c8951ae0d340824b4b4f19ac Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Mon, 16 May 2011 18:20:50 -0500
Subject: Adding the is_admin field now per Elrond's sane request / advice. ;)
---
mediagoblin/models.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/mediagoblin/models.py b/mediagoblin/models.py
index 4a867323..edb1d46d 100644
--- a/mediagoblin/models.py
+++ b/mediagoblin/models.py
@@ -42,7 +42,8 @@ class User(Document):
'pw_hash': unicode,
'email_verified': bool,
'status': unicode,
- 'verification_key': unicode
+ 'verification_key': unicode,
+ 'is_admin': bool,
}
required_fields = ['username', 'created', 'pw_hash', 'email']
@@ -51,7 +52,8 @@ class User(Document):
'created': datetime.datetime.utcnow,
'email_verified': False,
'status': u'needs_email_verification',
- 'verification_key': lambda: unicode( uuid.uuid4() ) }
+ 'verification_key': lambda: unicode(uuid.uuid4()),
+ 'is_admin': False}
def check_login(self, password):
"""
--
cgit v1.2.3
From 37af09a2e51394c630bf7efd1718b77a574b272d Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Mon, 16 May 2011 18:22:13 -0500
Subject: Require that the slug field have only unique values.
---
mediagoblin/models.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/mediagoblin/models.py b/mediagoblin/models.py
index edb1d46d..cdb06a35 100644
--- a/mediagoblin/models.py
+++ b/mediagoblin/models.py
@@ -99,6 +99,10 @@ class MediaEntry(Document):
'created': datetime.datetime.utcnow,
'state': u'unprocessed'}
+ indexes = [
+ {'fields': 'slug',
+ 'unique': True}]
+
def main_mediafile(self):
pass
--
cgit v1.2.3
From f0545ddebd1a313249f6b39fdf96ba879a78e8b2 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Mon, 16 May 2011 18:23:27 -0500
Subject: My name's Chris Webber and I'm pedantic about lines not going over 80
characters.
---
mediagoblin/models.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/models.py b/mediagoblin/models.py
index cdb06a35..7cacc519 100644
--- a/mediagoblin/models.py
+++ b/mediagoblin/models.py
@@ -109,7 +109,8 @@ class MediaEntry(Document):
def generate_slug(self):
self['slug'] = util.slugify(self['title'])
- duplicate = mediagoblin_globals.database.media_entries.find_one({'slug': self['slug']})
+ duplicate = mediagoblin_globals.database.media_entries.find_one(
+ {'slug': self['slug']})
if duplicate:
self['slug'] = "%s-%s" % (self['_id'], self['slug'])
--
cgit v1.2.3
From 931f318cbc571419510b1ad37298c981df2f16b0 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Mon, 16 May 2011 18:28:49 -0500
Subject: Actually we only need unique slugs per uploader.
But I want to fix http://bugs.foocorp.net/issues/340 first.
---
mediagoblin/models.py | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/mediagoblin/models.py b/mediagoblin/models.py
index 7cacc519..1bc1da60 100644
--- a/mediagoblin/models.py
+++ b/mediagoblin/models.py
@@ -99,9 +99,11 @@ class MediaEntry(Document):
'created': datetime.datetime.utcnow,
'state': u'unprocessed'}
- indexes = [
- {'fields': 'slug',
- 'unique': True}]
+ # Actually we should referene uniqueness by uploader, but we
+ # should fix http://bugs.foocorp.net/issues/340 first.
+ # indexes = [
+ # {'fields': ['uploader', 'slug'],
+ # 'unique': True}]
def main_mediafile(self):
pass
--
cgit v1.2.3
From 0f18ed8f5e179326721221df93734864074bc185 Mon Sep 17 00:00:00 2001
From: Elrond
Date: Wed, 18 May 2011 00:44:10 +0200
Subject: Move models into new db/ directory
The database is a central point of interest/discussion.
Represent that by its own directory.
This will surely become more interesting when we have
migrations for example.
---
mediagoblin/app.py | 3 +-
mediagoblin/celery_setup/from_celery.py | 3 +-
mediagoblin/db/__init__.py | 0
mediagoblin/db/models.py | 128 ++++++++++++++++++++++++++++++++
mediagoblin/models.py | 128 --------------------------------
mediagoblin/views.py | 2 +-
6 files changed, 133 insertions(+), 131 deletions(-)
create mode 100644 mediagoblin/db/__init__.py
create mode 100644 mediagoblin/db/models.py
delete mode 100644 mediagoblin/models.py
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index d124558d..908bb19c 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -21,7 +21,8 @@ import mongokit
from paste.deploy.converters import asbool, asint
from webob import Request, exc
-from mediagoblin import routing, util, models, storage, staticdirect
+from mediagoblin import routing, util, storage, staticdirect
+from mediagoblin.db import models
from mediagoblin.globals import setup_globals
from mediagoblin.celery_setup import setup_celery_from_config
diff --git a/mediagoblin/celery_setup/from_celery.py b/mediagoblin/celery_setup/from_celery.py
index 55e638b9..65dcca40 100644
--- a/mediagoblin/celery_setup/from_celery.py
+++ b/mediagoblin/celery_setup/from_celery.py
@@ -20,7 +20,8 @@ import mongokit
from paste.deploy.loadwsgi import NicerConfigParser
from paste.deploy.converters import asint, asbool
-from mediagoblin import storage, models
+from mediagoblin import storage
+from mediagoblin.db import models
from mediagoblin.celery_setup import setup_celery_from_config
from mediagoblin.globals import setup_globals
from mediagoblin import globals as mgoblin_globals
diff --git a/mediagoblin/db/__init__.py b/mediagoblin/db/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
new file mode 100644
index 00000000..1bc1da60
--- /dev/null
+++ b/mediagoblin/db/models.py
@@ -0,0 +1,128 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import datetime, uuid
+
+from mongokit import Document, Set
+
+from mediagoblin import util
+from mediagoblin.auth import lib as auth_lib
+from mediagoblin import globals as mediagoblin_globals
+
+###################
+# Custom validators
+###################
+
+########
+# Models
+########
+
+
+class User(Document):
+ __collection__ = 'users'
+
+ structure = {
+ 'username': unicode,
+ 'email': unicode,
+ 'created': datetime.datetime,
+ 'plugin_data': dict, # plugins can dump stuff here.
+ 'pw_hash': unicode,
+ 'email_verified': bool,
+ 'status': unicode,
+ 'verification_key': unicode,
+ 'is_admin': bool,
+ }
+
+ required_fields = ['username', 'created', 'pw_hash', 'email']
+
+ default_values = {
+ 'created': datetime.datetime.utcnow,
+ 'email_verified': False,
+ 'status': u'needs_email_verification',
+ 'verification_key': lambda: unicode(uuid.uuid4()),
+ 'is_admin': False}
+
+ def check_login(self, password):
+ """
+ See if a user can login with this password
+ """
+ return auth_lib.bcrypt_check_password(
+ password, self['pw_hash'])
+
+
+class MediaEntry(Document):
+ __collection__ = 'media_entries'
+
+ structure = {
+ 'uploader': User,
+ 'title': unicode,
+ 'slug': unicode,
+ 'created': datetime.datetime,
+ 'description': unicode,
+ 'media_type': unicode,
+ 'media_data': dict, # extra data relevant to this media_type
+ 'plugin_data': dict, # plugins can dump stuff here.
+ 'tags': [unicode],
+ 'state': unicode,
+
+ # For now let's assume there can only be one main file queued
+ # at a time
+ 'queued_media_file': [unicode],
+
+ # A dictionary of logical names to filepaths
+ 'media_files': dict,
+
+ # The following should be lists of lists, in appropriate file
+ # record form
+ 'attachment_files': list,
+
+ # This one should just be a single file record
+ 'thumbnail_file': [unicode]}
+
+ required_fields = [
+ 'uploader', 'created', 'media_type']
+
+ default_values = {
+ 'created': datetime.datetime.utcnow,
+ 'state': u'unprocessed'}
+
+ # Actually we should referene uniqueness by uploader, but we
+ # should fix http://bugs.foocorp.net/issues/340 first.
+ # indexes = [
+ # {'fields': ['uploader', 'slug'],
+ # 'unique': True}]
+
+ def main_mediafile(self):
+ pass
+
+ def generate_slug(self):
+ self['slug'] = util.slugify(self['title'])
+
+ duplicate = mediagoblin_globals.database.media_entries.find_one(
+ {'slug': self['slug']})
+
+ if duplicate:
+ self['slug'] = "%s-%s" % (self['_id'], self['slug'])
+
+REGISTER_MODELS = [MediaEntry, User]
+
+
+def register_models(connection):
+ """
+ Register all models in REGISTER_MODELS with this connection.
+ """
+ connection.register(REGISTER_MODELS)
+
diff --git a/mediagoblin/models.py b/mediagoblin/models.py
deleted file mode 100644
index 1bc1da60..00000000
--- a/mediagoblin/models.py
+++ /dev/null
@@ -1,128 +0,0 @@
-# GNU MediaGoblin -- federated, autonomous media hosting
-# Copyright (C) 2011 Free Software Foundation, Inc
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with this program. If not, see .
-
-import datetime, uuid
-
-from mongokit import Document, Set
-
-from mediagoblin import util
-from mediagoblin.auth import lib as auth_lib
-from mediagoblin import globals as mediagoblin_globals
-
-###################
-# Custom validators
-###################
-
-########
-# Models
-########
-
-
-class User(Document):
- __collection__ = 'users'
-
- structure = {
- 'username': unicode,
- 'email': unicode,
- 'created': datetime.datetime,
- 'plugin_data': dict, # plugins can dump stuff here.
- 'pw_hash': unicode,
- 'email_verified': bool,
- 'status': unicode,
- 'verification_key': unicode,
- 'is_admin': bool,
- }
-
- required_fields = ['username', 'created', 'pw_hash', 'email']
-
- default_values = {
- 'created': datetime.datetime.utcnow,
- 'email_verified': False,
- 'status': u'needs_email_verification',
- 'verification_key': lambda: unicode(uuid.uuid4()),
- 'is_admin': False}
-
- def check_login(self, password):
- """
- See if a user can login with this password
- """
- return auth_lib.bcrypt_check_password(
- password, self['pw_hash'])
-
-
-class MediaEntry(Document):
- __collection__ = 'media_entries'
-
- structure = {
- 'uploader': User,
- 'title': unicode,
- 'slug': unicode,
- 'created': datetime.datetime,
- 'description': unicode,
- 'media_type': unicode,
- 'media_data': dict, # extra data relevant to this media_type
- 'plugin_data': dict, # plugins can dump stuff here.
- 'tags': [unicode],
- 'state': unicode,
-
- # For now let's assume there can only be one main file queued
- # at a time
- 'queued_media_file': [unicode],
-
- # A dictionary of logical names to filepaths
- 'media_files': dict,
-
- # The following should be lists of lists, in appropriate file
- # record form
- 'attachment_files': list,
-
- # This one should just be a single file record
- 'thumbnail_file': [unicode]}
-
- required_fields = [
- 'uploader', 'created', 'media_type']
-
- default_values = {
- 'created': datetime.datetime.utcnow,
- 'state': u'unprocessed'}
-
- # Actually we should referene uniqueness by uploader, but we
- # should fix http://bugs.foocorp.net/issues/340 first.
- # indexes = [
- # {'fields': ['uploader', 'slug'],
- # 'unique': True}]
-
- def main_mediafile(self):
- pass
-
- def generate_slug(self):
- self['slug'] = util.slugify(self['title'])
-
- duplicate = mediagoblin_globals.database.media_entries.find_one(
- {'slug': self['slug']})
-
- if duplicate:
- self['slug'] = "%s-%s" % (self['_id'], self['slug'])
-
-REGISTER_MODELS = [MediaEntry, User]
-
-
-def register_models(connection):
- """
- Register all models in REGISTER_MODELS with this connection.
- """
- connection.register(REGISTER_MODELS)
-
diff --git a/mediagoblin/views.py b/mediagoblin/views.py
index 602f1098..60d34908 100644
--- a/mediagoblin/views.py
+++ b/mediagoblin/views.py
@@ -20,7 +20,7 @@ from webob import Response, exc
import wtforms
from pymongo import DESCENDING
from mongokit import ObjectId
-from mediagoblin import models
+from mediagoblin.db import models
import gettext
def root_view(request):
--
cgit v1.2.3
From a4bae8700e2186adb91d5c0a5198e7a8923143c6 Mon Sep 17 00:00:00 2001
From: Elrond
Date: Wed, 18 May 2011 01:03:40 +0200
Subject: Move "connect to database" into db/util.py
---
mediagoblin/app.py | 8 ++------
mediagoblin/db/util.py | 11 +++++++++++
2 files changed, 13 insertions(+), 6 deletions(-)
create mode 100644 mediagoblin/db/util.py
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index 908bb19c..c94b5f6d 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -17,12 +17,12 @@
import urllib
import routes
-import mongokit
from paste.deploy.converters import asbool, asint
from webob import Request, exc
from mediagoblin import routing, util, storage, staticdirect
from mediagoblin.db import models
+from mediagoblin.db.util import connect_database
from mediagoblin.globals import setup_globals
from mediagoblin.celery_setup import setup_celery_from_config
@@ -118,11 +118,7 @@ class MediaGoblinApp(object):
def paste_app_factory(global_config, **app_config):
# Get the database connection
- port = app_config.get('db_port')
- if port:
- port = asint(port)
- connection = mongokit.Connection(
- app_config.get('db_host'), port)
+ connection = connect_database(app_config)
# Set up the storage systems.
public_store = storage.storage_system_from_paste_config(
diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py
new file mode 100644
index 00000000..89e0dbef
--- /dev/null
+++ b/mediagoblin/db/util.py
@@ -0,0 +1,11 @@
+import mongokit
+
+
+def connect_database(app_config):
+ """Connect to the main database, take config from app_config"""
+ port = app_config.get('db_port')
+ if port:
+ port = asint(port)
+ connection = mongokit.Connection(
+ app_config.get('db_host'), port)
+ return connection
--
cgit v1.2.3
From 254bc43174ecad984ce895c10e6be7926c52cc22 Mon Sep 17 00:00:00 2001
From: Elrond
Date: Wed, 18 May 2011 11:32:29 +0200
Subject: Move ObjectId, DESCENDING to db.util
We used to import those from pymongo and mongokit directly.
We should import them from a single place. So let's try
db.util for this.
---
mediagoblin/db/util.py | 2 ++
mediagoblin/process_media/__init__.py | 4 ++--
mediagoblin/user_pages/views.py | 3 +--
mediagoblin/util.py | 4 ++--
mediagoblin/views.py | 3 +--
5 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py
index 89e0dbef..56f22d7e 100644
--- a/mediagoblin/db/util.py
+++ b/mediagoblin/db/util.py
@@ -1,4 +1,6 @@
import mongokit
+from pymongo import DESCENDING
+from mongokit import ObjectId
def connect_database(app_config):
diff --git a/mediagoblin/process_media/__init__.py b/mediagoblin/process_media/__init__.py
index 3c4d0ca1..4f06a686 100644
--- a/mediagoblin/process_media/__init__.py
+++ b/mediagoblin/process_media/__init__.py
@@ -15,7 +15,7 @@
# along with this program. If not, see .
import Image
-import mongokit
+from mediagoblin.db.util import ObjectId
from celery.task import task
from mediagoblin.globals import database, queue_store, public_store
@@ -27,7 +27,7 @@ THUMB_SIZE = 200, 200
@task
def process_media_initial(media_id):
entry = database.MediaEntry.one(
- {'_id': mongokit.ObjectId(media_id)})
+ {'_id': ObjectId(media_id)})
queued_filepath = entry['queued_media_file']
queued_file = queue_store.get_file(queued_filepath, 'r')
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index c99556c2..1ab3c8ef 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -15,8 +15,7 @@
# along with this program. If not, see .
from webob import Response, exc
-from pymongo import DESCENDING
-from mongokit import ObjectId
+from mediagoblin.db.util import ObjectId, DESCENDING
import wtforms
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index a66e2ba5..680ff62e 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -21,7 +21,7 @@ import smtplib
import sys
import re
import jinja2
-import mongokit
+from mediagoblin.db.util import ObjectId
import translitcodec
from mediagoblin import globals as mgoblin_globals
@@ -83,7 +83,7 @@ def setup_user_in_request(request):
user = None
user = request.app.db.User.one(
- {'_id': mongokit.ObjectId(request.session['user_id'])})
+ {'_id': ObjectId(request.session['user_id'])})
if not user:
# Something's wrong... this user doesn't exist? Invalidate
diff --git a/mediagoblin/views.py b/mediagoblin/views.py
index 60d34908..5bc04b66 100644
--- a/mediagoblin/views.py
+++ b/mediagoblin/views.py
@@ -18,9 +18,8 @@ import datetime
from webob import Response, exc
import wtforms
-from pymongo import DESCENDING
-from mongokit import ObjectId
from mediagoblin.db import models
+from mediagoblin.db.util import ObjectId, DESCENDING
import gettext
def root_view(request):
--
cgit v1.2.3
From 1815f5ce2e1a12c04e9521dfe798c28b5186e458 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Wed, 18 May 2011 08:37:48 -0500
Subject: Adding copyright headers and explaining why these unused imports are
here
---
mediagoblin/db/__init__.py | 15 +++++++++++++++
mediagoblin/db/util.py | 18 ++++++++++++++++++
2 files changed, 33 insertions(+)
diff --git a/mediagoblin/db/__init__.py b/mediagoblin/db/__init__.py
index e69de29b..c129cbf8 100644
--- a/mediagoblin/db/__init__.py
+++ b/mediagoblin/db/__init__.py
@@ -0,0 +1,15 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py
index 56f22d7e..4828e3d7 100644
--- a/mediagoblin/db/util.py
+++ b/mediagoblin/db/util.py
@@ -1,4 +1,22 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
import mongokit
+
+# Imports that other modules might use
from pymongo import DESCENDING
from mongokit import ObjectId
--
cgit v1.2.3
From 468bc8afce0eab35ca3d403708a27187f65e96ac Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Wed, 18 May 2011 08:39:09 -0500
Subject: Need to import asint for users who specify ports via config file
---
mediagoblin/db/util.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py
index 4828e3d7..f70a5826 100644
--- a/mediagoblin/db/util.py
+++ b/mediagoblin/db/util.py
@@ -16,6 +16,8 @@
import mongokit
+from paste.deploy.converters import asint
+
# Imports that other modules might use
from pymongo import DESCENDING
from mongokit import ObjectId
--
cgit v1.2.3
From 3262ad1dbbc1919de2393e11900f5a47ac5dcd75 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Wed, 18 May 2011 08:44:57 -0500
Subject: Renaming connect_database to connect_database_from_config and using
in from_celery
---
mediagoblin/app.py | 4 ++--
mediagoblin/celery_setup/from_celery.py | 8 +++-----
mediagoblin/db/util.py | 2 +-
3 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index c94b5f6d..60adba56 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -22,7 +22,7 @@ from webob import Request, exc
from mediagoblin import routing, util, storage, staticdirect
from mediagoblin.db import models
-from mediagoblin.db.util import connect_database
+from mediagoblin.db.util import connect_database_from_config
from mediagoblin.globals import setup_globals
from mediagoblin.celery_setup import setup_celery_from_config
@@ -118,7 +118,7 @@ class MediaGoblinApp(object):
def paste_app_factory(global_config, **app_config):
# Get the database connection
- connection = connect_database(app_config)
+ connection = connect_database_from_config(app_config)
# Set up the storage systems.
public_store = storage.storage_system_from_paste_config(
diff --git a/mediagoblin/celery_setup/from_celery.py b/mediagoblin/celery_setup/from_celery.py
index 65dcca40..57b52f56 100644
--- a/mediagoblin/celery_setup/from_celery.py
+++ b/mediagoblin/celery_setup/from_celery.py
@@ -22,6 +22,7 @@ from paste.deploy.converters import asint, asbool
from mediagoblin import storage
from mediagoblin.db import models
+from mediagoblin.db.util import connect_database_from_config
from mediagoblin.celery_setup import setup_celery_from_config
from mediagoblin.globals import setup_globals
from mediagoblin import globals as mgoblin_globals
@@ -69,11 +70,8 @@ def setup_self(setup_globals_func=setup_globals):
settings_module=OUR_MODULENAME,
set_environ=False)
- port = mgoblin_section.get('db_port')
- if port:
- port = asint(port)
- connection = mongokit.Connection(
- mgoblin_section.get('db_host'), port)
+ connection = connect_database_from_config(mgoblin_section)
+
db = connection[mgoblin_section.get('db_name', 'mediagoblin')]
models.register_models(connection)
diff --git a/mediagoblin/db/util.py b/mediagoblin/db/util.py
index f70a5826..407caf05 100644
--- a/mediagoblin/db/util.py
+++ b/mediagoblin/db/util.py
@@ -23,7 +23,7 @@ from pymongo import DESCENDING
from mongokit import ObjectId
-def connect_database(app_config):
+def connect_database_from_config(app_config):
"""Connect to the main database, take config from app_config"""
port = app_config.get('db_port')
if port:
--
cgit v1.2.3
From ae85ed0f971147ce7cee9ce02b498f909d21ce79 Mon Sep 17 00:00:00 2001
From: Bernhard Keller
Date: Wed, 18 May 2011 17:32:49 +0200
Subject: added Pagination class, usage description in Pagination,__call__
added pagination.html, object_gallery.html as templates
---
mediagoblin/templates/mediagoblin/root.html | 2 +-
.../templates/mediagoblin/user_pages/user.html | 11 +--
.../mediagoblin/utils/object_gallery.html | 36 +++++++++
.../templates/mediagoblin/utils/pagination.html | 41 +++++++++++
mediagoblin/user_pages/views.py | 23 ++++--
mediagoblin/util.py | 86 ++++++++++++++++++++++
6 files changed, 183 insertions(+), 16 deletions(-)
create mode 100644 mediagoblin/templates/mediagoblin/utils/object_gallery.html
create mode 100644 mediagoblin/templates/mediagoblin/utils/pagination.html
diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html
index e2b2730a..a93a7c75 100644
--- a/mediagoblin/templates/mediagoblin/root.html
+++ b/mediagoblin/templates/mediagoblin/root.html
@@ -53,4 +53,4 @@
-{% endblock %}
+{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/user.html b/mediagoblin/templates/mediagoblin/user_pages/user.html
index 5c8692fc..48516679 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/user.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/user.html
@@ -23,14 +23,9 @@
{#- Should we outsource such a media 'gallery' view to it's own file?
It could be useful for the home page and other views too -#}
{% else %}
{# This *should* not occur as the view makes sure we pass in a user. #}
diff --git a/mediagoblin/templates/mediagoblin/utils/object_gallery.html b/mediagoblin/templates/mediagoblin/utils/object_gallery.html
new file mode 100644
index 00000000..6e59c380
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/utils/object_gallery.html
@@ -0,0 +1,36 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+
+
+
diff --git a/mediagoblin/templates/mediagoblin/utils/pagination.html b/mediagoblin/templates/mediagoblin/utils/pagination.html
new file mode 100644
index 00000000..80b4b820
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/utils/pagination.html
@@ -0,0 +1,41 @@
+{# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+
+
+{% macro render_pagination(pagination) %}
+
+{# only display if {{pagination}} is defined #}
+
+{% if pagination %}
+
-{% endif %}
+
{% endmacro %}
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index 55d60c6b..26c67425 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -18,7 +18,8 @@ from webob import Response, exc
from pymongo import DESCENDING
from mongokit import ObjectId
import wtforms
-from ..util import Pagination
+from mediagoblin.util import Pagination
+from pymongo import ASCENDING, DESCENDING
def user_home(request):
"""'Homepage' of a User()"""
@@ -28,12 +29,12 @@ def user_home(request):
if not user:
return exc.HTTPNotFound()
- pagination = Pagination()
- media_entries = pagination(
- { 'per_page': 2,
- 'request': request,
- 'collection':'MediaEntry',
- 'query': { 'uploader':user, 'state':'processed'} } )
+ cursor = request.db.MediaEntry \
+ .find({'uploader': user, 'state': 'processed'}) \
+ .sort('created', DESCENDING)
+
+ pagination = Pagination(2, cursor, request)
+ media_entries = pagination()
#if no data is available, return NotFound
if media_entries == None:
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index 0f28dd79..b79d6b05 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -27,7 +27,6 @@ import translitcodec
from mediagoblin import globals as mgoblin_globals
import urllib
-from pymongo import ASCENDING, DESCENDING
from math import ceil
@@ -300,53 +299,20 @@ class Pagination(object):
"""
Pagination class
"""
- def __init__(self):
- pass
-
- def __call__(self, args):
- """
- input values:
- {'page': ..., --- requested page
- 'per_page': ..., --- objects per page
- 'request': ..., --- webob request object for url generation
- 'collection' ... --- db collection, thats to be queried
- 'query': {'user': xxx}, query restrictions, db.collection.find(query)
- }
-
- add:
- option for sorting attribute
- ascending, descending option
- range based pagination
- """
- self.per_page = args['per_page']
- self.request = args['request']
-
+ def __init__(self, per_page, cursor, request):
try:
- self.page = abs(int(args['request'].str_GET['page']))
- # set default page, if page value is not set
+ self.page = int(request.str_GET['page'])
except KeyError:
self.page = 1
- # return None(404 Error) if page is set, but has no value or has an invalid value
- except ValueError:
- return None
-
- ######################################################
- #
- # db queries should be changed into range based pagination
- # save count and current page in some user session data
- #
- ######################################################
-
- collection = getattr(self.request.db, args['collection'])
-
- self.total_count = collection.find(args['query']).count()
-
- #check if requested page is valid, not larger than available number of pages
- if self.page > self.pages:
- return None
-
- return collection.find(args['query']).sort('created',DESCENDING) \
- .skip((self.page-1)*self.per_page).limit(self.per_page)
+
+ self.per_page = per_page
+ self.cursor = cursor
+ self.request = request
+ self.total_count = self.cursor.count()
+
+ def __call__(self):
+ return self.cursor.skip((self.page-1)*self.per_page) \
+ .limit(self.per_page)
@property
def pages(self):
--
cgit v1.2.3
From 44e3e917fbfc89409bac08d500c5a9246e0dc5f4 Mon Sep 17 00:00:00 2001
From: Bernhard Keller
Date: Thu, 19 May 2011 20:37:04 +0200
Subject: removed request arg from Pagination class added get_page_url() in
Pagination class, to generate proper urls without losing other get arguments
---
.../templates/mediagoblin/user_pages/user.html | 2 --
.../mediagoblin/utils/object_gallery.html | 35 ++++++++++----------
.../templates/mediagoblin/utils/pagination.html | 23 +++++++------
mediagoblin/user_pages/views.py | 9 +++--
mediagoblin/util.py | 38 +++++++++++++++-------
5 files changed, 61 insertions(+), 46 deletions(-)
diff --git a/mediagoblin/templates/mediagoblin/user_pages/user.html b/mediagoblin/templates/mediagoblin/user_pages/user.html
index 48516679..d1809e80 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/user.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/user.html
@@ -20,8 +20,6 @@
{% if user %}
User page for '{{ user.username }}'
- {#- Should we outsource such a media 'gallery' view to it's own file?
- It could be useful for the home page and other views too -#}
{% include "mediagoblin/utils/object_gallery.html" %}
diff --git a/mediagoblin/templates/mediagoblin/utils/object_gallery.html b/mediagoblin/templates/mediagoblin/utils/object_gallery.html
index 9e8c1875..8ae337f5 100644
--- a/mediagoblin/templates/mediagoblin/utils/object_gallery.html
+++ b/mediagoblin/templates/mediagoblin/utils/object_gallery.html
@@ -16,22 +16,21 @@
# along with this program. If not, see .
#}
-{% import 'mediagoblin/utils/pagination.html' as paginationmacro %}
+{% block object_gallery_content -%}
+
+{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/utils/pagination.html b/mediagoblin/templates/mediagoblin/utils/pagination.html
index 685a1bb9..b74cbfcf 100644
--- a/mediagoblin/templates/mediagoblin/utils/pagination.html
+++ b/mediagoblin/templates/mediagoblin/utils/pagination.html
@@ -15,22 +15,21 @@
# along with this program. If not, see .
#}
+{# only display if {{pagination}} is defined #}
-{% macro render_pagination(pagination) %}
-
- {# only display if {{pagination}} is defined #}
-
- {% if pagination %}
-
--
cgit v1.2.3
From 571198c938d66d2cc4d7d7a0d261633d51061968 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 20 May 2011 18:49:04 -0500
Subject: Now you can set CELERY_ALWAYS_EAGER environment variable so that you
don't have to run celeryd at the same time.
This should make Elrond happy ;)
---
mediagoblin/app.py | 8 +++++++-
mediagoblin/celery_setup/__init__.py | 5 +++++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index 640ffc45..714404de 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -14,6 +14,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
+import os
import urllib
import routes
@@ -138,7 +139,12 @@ def paste_app_factory(global_config, **app_config):
raise ImproperlyConfigured(
"One of direct_remote_path or direct_remote_paths must be provided")
- setup_celery_from_config(app_config, global_config)
+ if asbool(os.environ.get('CELERY_ALWAYS_EAGER')):
+ setup_celery_from_config(
+ app_config, global_config,
+ force_celery_always_eager=True)
+ else:
+ setup_celery_from_config(app_config, global_config)
mgoblin_app = MediaGoblinApp(
connection, db,
diff --git a/mediagoblin/celery_setup/__init__.py b/mediagoblin/celery_setup/__init__.py
index 551b2741..1a77cc62 100644
--- a/mediagoblin/celery_setup/__init__.py
+++ b/mediagoblin/celery_setup/__init__.py
@@ -76,6 +76,7 @@ DEFAULT_SETTINGS_MODULE = 'mediagoblin.celery_setup.dummy_settings_module'
def setup_celery_from_config(app_config, global_config,
settings_module=DEFAULT_SETTINGS_MODULE,
+ force_celery_always_eager=False,
set_environ=True):
"""
Take a mediagoblin app config and the global config from a paste
@@ -85,6 +86,7 @@ def setup_celery_from_config(app_config, global_config,
- app_config: the application config section
- global_config: the entire paste config, all sections
- settings_module: the module to populate, as a string
+ -
- set_environ: if set, this will CELERY_CONFIG_MODULE to the
settings_module
"""
@@ -136,6 +138,9 @@ def setup_celery_from_config(app_config, global_config,
celery_imports = celery_settings.setdefault('CELERY_IMPORTS', [])
celery_imports.extend(MANDATORY_CELERY_IMPORTS)
+ if force_celery_always_eager:
+ celery_settings['CELERY_ALWAYS_EAGER'] = True
+
__import__(settings_module)
this_module = sys.modules[settings_module]
--
cgit v1.2.3
From 01674e105c4269d53453257f69f7512e8b5d40a8 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 20 May 2011 19:12:32 -0500
Subject: Make sure that a MediaEntry does belong to this appropriate user in
the decorator. (Thanks Elrond)
---
mediagoblin/decorators.py | 22 +++++++++++++++++-----
mediagoblin/user_pages/views.py | 4 ++--
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py
index 2e7ad386..34a471cb 100644
--- a/mediagoblin/decorators.py
+++ b/mediagoblin/decorators.py
@@ -15,6 +15,7 @@
# along with this program. If not, see .
+from bson.errors import InvalidId
from webob import exc
from mediagoblin.db.util import ObjectId
@@ -65,20 +66,31 @@ def uses_pagination(controller):
return _make_safe(wrapper, controller)
-def get_media_entry(controller):
+def get_user_media_entry(controller):
"""
Pass in a MediaEntry based off of a url component
"""
def wrapper(request, *args, **kwargs):
+ user = request.db.User.find_one(
+ {'username': request.matchdict['user']})
+
+ if not user:
+ return exc.HTTPNotFound()
+
media = request.db.MediaEntry.find_one(
{'slug': request.matchdict['media'],
- 'state': 'processed'})
+ 'state': 'processed',
+ 'uploader._id': user['_id']})
# no media via slug? Grab it via ObjectId
if not media:
- media = request.db.MediaEntry.find_one(
- {'_id': ObjectId(request.matchdict['media']),
- 'state': 'processed'})
+ try:
+ media = request.db.MediaEntry.find_one(
+ {'_id': ObjectId(request.matchdict['media']),
+ 'state': 'processed',
+ 'uploader._id': user['_id']})
+ except InvalidId:
+ return exc.HTTPNotFound()
# Still no media? Okay, 404.
if not media:
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index 0803749a..4a570579 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -18,7 +18,7 @@ from webob import Response, exc
from mediagoblin.db.util import DESCENDING
from mediagoblin.util import Pagination
-from mediagoblin.decorators import uses_pagination, get_media_entry
+from mediagoblin.decorators import uses_pagination, get_user_media_entry
@uses_pagination
@@ -52,7 +52,7 @@ def user_home(request, page):
'pagination': pagination}))
-@get_media_entry
+@get_user_media_entry
def media_home(request, media):
"""'Homepage' of a MediaEntry()"""
# Check that media uploader and user correspond.
--
cgit v1.2.3
From 5487efc4016da577796579797812f1753c55a6de Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 20 May 2011 19:12:44 -0500
Subject: This check is redundant now that it's handled by the decorator.
---
mediagoblin/user_pages/views.py | 4 ----
1 file changed, 4 deletions(-)
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index 4a570579..0d9833cd 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -55,10 +55,6 @@ def user_home(request, page):
@get_user_media_entry
def media_home(request, media):
"""'Homepage' of a MediaEntry()"""
- # Check that media uploader and user correspond.
- if media['uploader'].get('username') != request.matchdict['user']:
- return exc.HTTPNotFound()
-
template = request.template_env.get_template(
'mediagoblin/user_pages/media.html')
return Response(
--
cgit v1.2.3
From 2aa3bb1154758f7c5445985de2f0d4a00c6d78dc Mon Sep 17 00:00:00 2001
From: Will Kahn-Greene
Date: Fri, 20 May 2011 20:20:33 -0400
Subject: Moves virtualenv instructions to a place far far away
But seriously, moved them to the stop-gap wiki:
https://gitorious.org/mediagoblin/pages/HackingWithVirtualenv
---
docs/hackinghowto.rst | 136 ++++++--------------------------------------------
1 file changed, 15 insertions(+), 121 deletions(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index bf5278b3..939c9510 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -4,7 +4,6 @@
Hacking HOWTO
===============
-
So you want to hack on GNU MediaGoblin?
=======================================
@@ -26,12 +25,9 @@ new things.
Third you'll need to :ref:`get the requirements
`.
-Fourth, you'll need to build a development environment. For this step, there are two options:
-
-1. :ref:`buildout and bootstrap ` (easier) OR
-2. :ref:`virtualenv ` (more flexible, but harder)
-
-Pick one---don't do both!
+Fourth, you'll need to build a development environment. We use buildout,
+but if you want to use virtualenv, there's a set of mediocre not-very-supported
+steps in the `wiki `_.
.. _get-requirements-section:
@@ -65,15 +61,10 @@ requirements::
.. _hacking-with-buildout:
+
How to set up and maintain an environment for hacking with buildout
===================================================================
-.. Note::
-
- Either follow the instructions in this section OR follow the ones
- in :ref:`hacking-with-virtualenv`. But don't do both!
-
-
**Requirements**
No additional requirements.
@@ -124,104 +115,14 @@ To do this, do::
rm -rf bin develop-eggs eggs mediagoblin.egg-info parts user_dev
-Usually buildout works pretty great and is super easy, but if you get
-problems with python-dateutil conflicts on your system, you may need
-to use virtualenv instead.
-
-
-.. _hacking-with-virtualenv:
-
-How to set up and maintain an environment for hacking with virtualenv
-=====================================================================
-
-.. Note::
-
- Either follow the instructions in this section OR follow the ones
- in :ref:`hacking-with-buildout`. But don't do both!
-
-
-**Requirements**
-
-* virtualenv: http://pypi.python.org/pypi/virtualenv
-* virtualenv wrapper:
- http://www.doughellmann.com/projects/virtualenvwrapper/ (be sure to
- read the `install instructions
- `_)
-
-
-**Create a development environment**
-
-1. Clone the repository::
-
- git clone http://git.gitorious.org/mediagoblin/mediagoblin.git
-
-2. Create a virtual environment::
-
- mkvirtualenv --no-site-packages mediagoblin
-
-3. If that doesn't put you in the virutal environment you just
- created, then do::
-
- workon mediagoblin
-
-4. Run::
-
- python setup.py develop
-
-That's it!
-
-
-**Activating a virtual environment**
-
-When you want to work on GNU MediaGoblin, you need to activate the
-virtual environment like this::
-
- workon mediagoblin
-
-
-**Deactivating a virtual environment**
-
-If you want to deactivate it, you can do this::
-
- deactivate
-
-
-**Updating a virtual environment with dependency changes**
-
-1. Enter the virtual environment.
-
-2. Run::
-
- python setup.py develop
-
-
-**Updating a virtual environment with code changes**
-
-You don't need to do anything---code changes are automatically
-available.
-
-
-**Deleting a virtual environment**
-
-At some point you may want to delete your virtual environment.
-Perhaps it's to start over. Perhaps it's so you can test building
-development environments with virtualenv.
-
-To do this, do::
-
- rmvirtualenv mediagoblin
-
Running the server
==================
-If you did buildout, run::
+Run::
./bin/paster serve mediagoblin.ini --reload
-If you did virtualenv, run::
-
- paster serve mediagoblin.ini --reload
Running celeryd
===============
@@ -230,39 +131,29 @@ You need to do this if you want your media to process and actually
show up. It's probably a good idea in development to have the web
server (above) running in one terminal and celeryd in another window.
-If you did buildout, run::
+Run::
CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_celery ./bin/celeryd
-If you did virtualenv, run::
-
- CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_celery celeryd
Running the test suite
======================
-If you did buildout, run::
+Run::
./bin/nosetests
-If you did virtualenv, run::
-
- nosetests
Running a shell
===============
If you want a shell with your database pre-setup and an instantiated
-application ready and at your fingertips...
+application ready and at your fingertips....
-If you did buildout, run::
+Run::
./bin/gmg shell
-If you did virtualenv, run::
-
- gmg shell
-
Troubleshooting
===============
@@ -276,7 +167,8 @@ If you see this::
then make sure mongodb is installed and running.
-If it's installed, check the mongodb log. On my machine, that's ``/var/log/mongodb/mongodb.log``. If you see something like::
+If it's installed, check the mongodb log. On my machine, that's
+``/var/log/mongodb/mongodb.log``. If you see something like::
old lock file: /var/lib/mongodb/mongod.lock. probably means...
@@ -398,6 +290,8 @@ getting the hang of it:
it easier to get the hang of git if you're coming from other version
control systems
+There's also a git mission at `OpenHatch `_.
+
Learning other utilities
------------------------
@@ -406,5 +300,5 @@ The `OpenHatch `_ site has a series of
`training missions `_ which are
designed to help you learn how to use these tools.
-If you're new to tar, diff and patch, we highly recommend you sign up
-with OpenHatch and do the missions.
+If you're new to tar, diff, patch and git, we highly recommend you sign
+up with OpenHatch and do the missions.
--
cgit v1.2.3
From 693b674ce094b27a8f562bf55d7695302257cc82 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 20 May 2011 19:34:28 -0500
Subject: Added some stuff on how to run CELERY_ALWAYS_EAGER
---
docs/hackinghowto.rst | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 939c9510..8974b31d 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -136,6 +136,16 @@ Run::
CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_celery ./bin/celeryd
+Too much work? Don't want to run an http server and celeryd at the
+same time? For development purposes there's a shortcut::
+
+ CELERY_ALWAYS_EAGER=true ./bin/paster serve mediagoblin.ini --reload
+
+This way the web server will block on processing items until they are
+done, but you don't need to run celery separately (which is probably
+good enough for development purposes).
+
+
Running the test suite
======================
--
cgit v1.2.3
From c0bf3c807b1e5a88238e551eaa1491b51af3914d Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 20 May 2011 19:35:11 -0500
Subject: Clarified: don't do this in production!
---
docs/hackinghowto.rst | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 8974b31d..3544ec92 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -143,7 +143,8 @@ same time? For development purposes there's a shortcut::
This way the web server will block on processing items until they are
done, but you don't need to run celery separately (which is probably
-good enough for development purposes).
+good enough for development purposes, but something you almost
+certainly shouldn't do in production).
Running the test suite
--
cgit v1.2.3
From 0e84c707cb57b864fff4bdd438644c4313677893 Mon Sep 17 00:00:00 2001
From: Elrond
Date: Sat, 21 May 2011 16:38:34 +0200
Subject: Give Pagination.get_page_url() a request instead of path and GET
Makes calling Pagination.get_page_url() much simpler.
---
mediagoblin/templates/mediagoblin/utils/pagination.html | 9 +++------
mediagoblin/util.py | 8 ++++----
2 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/mediagoblin/templates/mediagoblin/utils/pagination.html b/mediagoblin/templates/mediagoblin/utils/pagination.html
index b74cbfcf..5ca5e09b 100644
--- a/mediagoblin/templates/mediagoblin/utils/pagination.html
+++ b/mediagoblin/templates/mediagoblin/utils/pagination.html
@@ -21,15 +21,13 @@
{% endif %}
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index d37d160e..a1af7bd0 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -29,8 +29,6 @@ from mediagoblin import globals as mgoblin_globals
import urllib
from math import ceil
import copy
-import decorators
-from webob import exc
TESTS_ENABLED = False
def _activate_testing():
@@ -353,11 +351,13 @@ class Pagination(object):
yield num
last = num
- def get_page_url(self, path_info, page_no, get_params=None):
+ def get_page_url(self, request, page_no):
"""
- Get a new page based of the path_info, the new page number,
+ Get a new page based of the request, the new page number,
and existing get parameters.
"""
+ path_info = request.path_info
+ get_params = request.GET
new_get_params = copy.copy(get_params or {})
new_get_params['page'] = page_no
return "%s?%s" % (
--
cgit v1.2.3
From 538a06e986a4ebebf5f670dd3d5af9ddb9501649 Mon Sep 17 00:00:00 2001
From: Elrond
Date: Sat, 21 May 2011 17:02:49 +0200
Subject: Fix doc string of get_page_url()
---
mediagoblin/util.py | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index a1af7bd0..f56bea43 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -353,8 +353,7 @@ class Pagination(object):
def get_page_url(self, request, page_no):
"""
- Get a new page based of the request, the new page number,
- and existing get parameters.
+ Get a new page url based of the request, and the new page number.
"""
path_info = request.path_info
get_params = request.GET
@@ -362,4 +361,3 @@ class Pagination(object):
new_get_params['page'] = page_no
return "%s?%s" % (
path_info, urllib.urlencode(new_get_params))
-
--
cgit v1.2.3
From dbb92c602075c768d88d0c21b774d75203af3fc1 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 22 May 2011 09:25:51 -0500
Subject: Move the ./bin/gmg shell command into its own module.
---
mediagoblin/gmg_commands/__init__.py | 58 ++----------------------------
mediagoblin/gmg_commands/shell.py | 70 ++++++++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+), 55 deletions(-)
create mode 100644 mediagoblin/gmg_commands/shell.py
diff --git a/mediagoblin/gmg_commands/__init__.py b/mediagoblin/gmg_commands/__init__.py
index 04e2ab6c..e585785c 100644
--- a/mediagoblin/gmg_commands/__init__.py
+++ b/mediagoblin/gmg_commands/__init__.py
@@ -14,71 +14,19 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-import code
import argparse
-import os
-from paste.deploy.loadwsgi import NicerConfigParser
-
-from mediagoblin.celery_setup import setup_celery_from_config
-from mediagoblin import app, util
-from mediagoblin import globals as mgoblin_globals
+from mediagoblin import util
SUBCOMMAND_MAP = {
'shell': {
- 'setup': 'mediagoblin.gmg_commands:shell_parser_setup',
- 'func': 'mediagoblin.gmg_commands:shell',
+ 'setup': 'mediagoblin.gmg_commands.shell:shell_parser_setup',
+ 'func': 'mediagoblin.gmg_commands.shell:shell',
'help': 'Run a shell with some tools pre-setup'},
}
-def shell_parser_setup(subparser):
- subparser.add_argument(
- '-cf', '--conf_file', default='mediagoblin.ini',
- help="Config file used to set up environment")
- subparser.add_argument(
- '-cs', '--app_section', default='app:mediagoblin',
- help="Section of the config file where the app config is stored.")
-
-
-SHELL_BANNER = """\
-GNU MediaGoblin shell!
-----------------------
-Available vars:
- - mgoblin_app: instantiated mediagoblin application
- - mgoblin_globals: mediagoblin.globals
- - db: database instance
-"""
-
-
-def shell(args):
- """
- """
- # Duplicated from from_celery.py, remove when we have the generic util
- parser = NicerConfigParser(args.conf_file)
- parser.read(args.conf_file)
- parser._defaults.setdefault(
- 'here', os.path.dirname(os.path.abspath(args.conf_file)))
- parser._defaults.setdefault(
- '__file__', os.path.abspath(args.conf_file))
-
- mgoblin_section = dict(parser.items(args.app_section))
- mgoblin_conf = dict(
- [(section_name, dict(parser.items(section_name)))
- for section_name in parser.sections()])
-
- mgoblin_app = app.paste_app_factory(
- mgoblin_conf, **mgoblin_section)
-
- code.interact(
- banner=SHELL_BANNER,
- local={
- 'mgoblin_app': mgoblin_app,
- 'mgoblin_globals': mgoblin_globals,
- 'db': mgoblin_globals.database})
-
-
def main_cli():
parser = argparse.ArgumentParser(
description='GNU MediaGoblin utilities.')
diff --git a/mediagoblin/gmg_commands/shell.py b/mediagoblin/gmg_commands/shell.py
new file mode 100644
index 00000000..5e70d556
--- /dev/null
+++ b/mediagoblin/gmg_commands/shell.py
@@ -0,0 +1,70 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+
+import code
+import os
+
+from paste.deploy.loadwsgi import NicerConfigParser
+
+from mediagoblin import app
+from mediagoblin import globals as mgoblin_globals
+
+
+def shell_parser_setup(subparser):
+ subparser.add_argument(
+ '-cf', '--conf_file', default='mediagoblin.ini',
+ help="Config file used to set up environment")
+ subparser.add_argument(
+ '-cs', '--app_section', default='app:mediagoblin',
+ help="Section of the config file where the app config is stored.")
+
+
+SHELL_BANNER = """\
+GNU MediaGoblin shell!
+----------------------
+Available vars:
+ - mgoblin_app: instantiated mediagoblin application
+ - mgoblin_globals: mediagoblin.globals
+ - db: database instance
+"""
+
+
+def shell(args):
+ """
+ """
+ # Duplicated from from_celery.py, remove when we have the generic util
+ parser = NicerConfigParser(args.conf_file)
+ parser.read(args.conf_file)
+ parser._defaults.setdefault(
+ 'here', os.path.dirname(os.path.abspath(args.conf_file)))
+ parser._defaults.setdefault(
+ '__file__', os.path.abspath(args.conf_file))
+
+ mgoblin_section = dict(parser.items(args.app_section))
+ mgoblin_conf = dict(
+ [(section_name, dict(parser.items(section_name)))
+ for section_name in parser.sections()])
+
+ mgoblin_app = app.paste_app_factory(
+ mgoblin_conf, **mgoblin_section)
+
+ code.interact(
+ banner=SHELL_BANNER,
+ local={
+ 'mgoblin_app': mgoblin_app,
+ 'mgoblin_globals': mgoblin_globals,
+ 'db': mgoblin_globals.database})
--
cgit v1.2.3
From 8820121ad125728613477f3dec098aa2df5f47ac Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 22 May 2011 09:56:33 -0500
Subject: Move the general applicaiton setup commands to a utility module
---
mediagoblin/gmg_commands/__init__.py | 6 ++---
mediagoblin/gmg_commands/shell.py | 22 +++---------------
mediagoblin/gmg_commands/util.py | 45 ++++++++++++++++++++++++++++++++++++
3 files changed, 51 insertions(+), 22 deletions(-)
create mode 100644 mediagoblin/gmg_commands/util.py
diff --git a/mediagoblin/gmg_commands/__init__.py b/mediagoblin/gmg_commands/__init__.py
index e585785c..9ece2ec5 100644
--- a/mediagoblin/gmg_commands/__init__.py
+++ b/mediagoblin/gmg_commands/__init__.py
@@ -16,7 +16,7 @@
import argparse
-from mediagoblin import util
+from mediagoblin import util as mg_util
SUBCOMMAND_MAP = {
@@ -39,8 +39,8 @@ def main_cli():
else:
subparser = subparsers.add_parser(command_name)
- setup_func = util.import_component(command_struct['setup'])
- exec_func = util.import_component(command_struct['func'])
+ setup_func = mg_util.import_component(command_struct['setup'])
+ exec_func = mg_util.import_component(command_struct['func'])
setup_func(subparser)
diff --git a/mediagoblin/gmg_commands/shell.py b/mediagoblin/gmg_commands/shell.py
index 5e70d556..9c0259de 100644
--- a/mediagoblin/gmg_commands/shell.py
+++ b/mediagoblin/gmg_commands/shell.py
@@ -16,12 +16,9 @@
import code
-import os
-from paste.deploy.loadwsgi import NicerConfigParser
-
-from mediagoblin import app
from mediagoblin import globals as mgoblin_globals
+from mediagoblin.gmg_commands import util as commands_util
def shell_parser_setup(subparser):
@@ -45,22 +42,9 @@ Available vars:
def shell(args):
"""
+ Setup a shell for the user
"""
- # Duplicated from from_celery.py, remove when we have the generic util
- parser = NicerConfigParser(args.conf_file)
- parser.read(args.conf_file)
- parser._defaults.setdefault(
- 'here', os.path.dirname(os.path.abspath(args.conf_file)))
- parser._defaults.setdefault(
- '__file__', os.path.abspath(args.conf_file))
-
- mgoblin_section = dict(parser.items(args.app_section))
- mgoblin_conf = dict(
- [(section_name, dict(parser.items(section_name)))
- for section_name in parser.sections()])
-
- mgoblin_app = app.paste_app_factory(
- mgoblin_conf, **mgoblin_section)
+ mgoblin_app = commands_util.setup_app(args)
code.interact(
banner=SHELL_BANNER,
diff --git a/mediagoblin/gmg_commands/util.py b/mediagoblin/gmg_commands/util.py
new file mode 100644
index 00000000..41a21a1e
--- /dev/null
+++ b/mediagoblin/gmg_commands/util.py
@@ -0,0 +1,45 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+
+import os
+
+from paste.deploy.loadwsgi import NicerConfigParser
+
+from mediagoblin import app
+
+
+def setup_app(args):
+ """
+ Setup the application after reading the mediagoblin config files
+ """
+ # Duplicated from from_celery.py, remove when we have the generic util
+ parser = NicerConfigParser(args.conf_file)
+ parser.read(args.conf_file)
+ parser._defaults.setdefault(
+ 'here', os.path.dirname(os.path.abspath(args.conf_file)))
+ parser._defaults.setdefault(
+ '__file__', os.path.abspath(args.conf_file))
+
+ mgoblin_section = dict(parser.items(args.app_section))
+ mgoblin_conf = dict(
+ [(section_name, dict(parser.items(section_name)))
+ for section_name in parser.sections()])
+
+ mgoblin_app = app.paste_app_factory(
+ mgoblin_conf, **mgoblin_section)
+
+ return mgoblin_app
--
cgit v1.2.3
From 757f37a52d7854ed752d56c66498383125a05a9f Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 22 May 2011 10:52:53 -0500
Subject: User migration works (but the rest of the system isn't updated for
new user setup yet)
---
mediagoblin/db/migrations.py | 39 +++++++++++++++++++++++++++++++
mediagoblin/db/models.py | 6 ++++-
mediagoblin/gmg_commands/__init__.py | 4 ++++
mediagoblin/gmg_commands/migrate.py | 45 ++++++++++++++++++++++++++++++++++++
4 files changed, 93 insertions(+), 1 deletion(-)
create mode 100644 mediagoblin/db/migrations.py
create mode 100644 mediagoblin/gmg_commands/migrate.py
diff --git a/mediagoblin/db/migrations.py b/mediagoblin/db/migrations.py
new file mode 100644
index 00000000..d035b15b
--- /dev/null
+++ b/mediagoblin/db/migrations.py
@@ -0,0 +1,39 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+from mongokit import DocumentMigration
+
+from mediagoblin import globals as mediagoblin_globals
+
+
+class MediaEntryMigration(DocumentMigration):
+ def allmigration01_uploader_to_reference(self):
+ """
+ Old MediaEntry['uploader'] accidentally embedded the User instead
+ of referencing it. Fix that!
+ """
+ # uploader is an associative array
+ self.target = {'uploader': {'$type': 3}}
+ if not self.status:
+ for doc in self.collection.find(self.target):
+ self.update = {
+ '$set': {
+ 'uploader': doc['uploader']['_id']}}
+ self.collection.update(
+ self.target, self.update, multi=True, safe=True)
+
+
+MIGRATE_CLASSES = ['MediaEntry']
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index 8e7889eb..3fc8d9e8 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -21,6 +21,8 @@ from mongokit import Document, Set
from mediagoblin import util
from mediagoblin.auth import lib as auth_lib
from mediagoblin import globals as mediagoblin_globals
+from mediagoblin.db import migrations
+from mediagoblin.db.util import ObjectId
###################
# Custom validators
@@ -67,7 +69,7 @@ class MediaEntry(Document):
__collection__ = 'media_entries'
structure = {
- 'uploader': User,
+ 'uploader': ObjectId,
'title': unicode,
'slug': unicode,
'created': datetime.datetime,
@@ -99,6 +101,8 @@ class MediaEntry(Document):
'created': datetime.datetime.utcnow,
'state': u'unprocessed'}
+ migration_handler = migrations.MediaEntryMigration
+
# Actually we should referene uniqueness by uploader, but we
# should fix http://bugs.foocorp.net/issues/340 first.
# indexes = [
diff --git a/mediagoblin/gmg_commands/__init__.py b/mediagoblin/gmg_commands/__init__.py
index 9ece2ec5..d1f7bfc1 100644
--- a/mediagoblin/gmg_commands/__init__.py
+++ b/mediagoblin/gmg_commands/__init__.py
@@ -24,6 +24,10 @@ SUBCOMMAND_MAP = {
'setup': 'mediagoblin.gmg_commands.shell:shell_parser_setup',
'func': 'mediagoblin.gmg_commands.shell:shell',
'help': 'Run a shell with some tools pre-setup'},
+ 'migrate': {
+ 'setup': 'mediagoblin.gmg_commands.migrate:migrate_parser_setup',
+ 'func': 'mediagoblin.gmg_commands.migrate:migrate',
+ 'help': 'Apply all unapplied bulk migrations to the database'},
}
diff --git a/mediagoblin/gmg_commands/migrate.py b/mediagoblin/gmg_commands/migrate.py
new file mode 100644
index 00000000..e04fb343
--- /dev/null
+++ b/mediagoblin/gmg_commands/migrate.py
@@ -0,0 +1,45 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+
+from mediagoblin.db import migrations
+from mediagoblin.gmg_commands import util as commands_util
+from mediagoblin import globals as mgoblin_globals
+
+
+def migrate_parser_setup(subparser):
+ subparser.add_argument(
+ '-cf', '--conf_file', default='mediagoblin.ini',
+ help="Config file used to set up environment")
+ subparser.add_argument(
+ '-cs', '--app_section', default='app:mediagoblin',
+ help="Section of the config file where the app config is stored.")
+
+
+def migrate(args):
+ mgoblin_app = commands_util.setup_app(args)
+ print "Applying migrations..."
+
+ for model_name in migrations.MIGRATE_CLASSES:
+ model = getattr(mgoblin_app.db, model_name)
+
+ if not hasattr(model, 'migration_handler') or not model.collection:
+ continue
+
+ migration = model.migration_handler(model)
+ migration.migrate_all(collection=model.collection)
+
+ print "... done."
--
cgit v1.2.3
From 16509be160470202147d3b711126c7928790777d Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 22 May 2011 16:06:45 -0500
Subject: Update all the views so that they use the uploader reference instead
of uploader embedding
---
mediagoblin/db/models.py | 9 +++++++--
mediagoblin/decorators.py | 4 ++--
mediagoblin/submit/views.py | 2 +-
mediagoblin/templates/mediagoblin/user_pages/media.html | 4 ++--
mediagoblin/user_pages/views.py | 2 +-
5 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index 3fc8d9e8..37420834 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -127,17 +127,22 @@ class MediaEntry(Document):
Use a slug if we have one, else use our '_id'.
"""
+ uploader = self.uploader()
+
if self.get('slug'):
return urlgen(
'mediagoblin.user_pages.media_home',
- user=self['uploader']['username'],
+ user=uploader['username'],
media=self['slug'])
else:
return urlgen(
'mediagoblin.user_pages.media_home',
- user=self['uploader']['username'],
+ user=uploader['username'],
media=unicode(self['_id']))
+ def uploader(self):
+ return self.db.User.find_one({'_id': self['uploader']})
+
REGISTER_MODELS = [MediaEntry, User]
diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py
index 34a471cb..ff3f0b5e 100644
--- a/mediagoblin/decorators.py
+++ b/mediagoblin/decorators.py
@@ -80,7 +80,7 @@ def get_user_media_entry(controller):
media = request.db.MediaEntry.find_one(
{'slug': request.matchdict['media'],
'state': 'processed',
- 'uploader._id': user['_id']})
+ 'uploader': user['_id']})
# no media via slug? Grab it via ObjectId
if not media:
@@ -88,7 +88,7 @@ def get_user_media_entry(controller):
media = request.db.MediaEntry.find_one(
{'_id': ObjectId(request.matchdict['media']),
'state': 'processed',
- 'uploader._id': user['_id']})
+ 'uploader': user['_id']})
except InvalidId:
return exc.HTTPNotFound()
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 95a416e2..262f2b12 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -46,7 +46,7 @@ def submit_start(request):
entry['title'] = request.POST['title'] or unicode(splitext(filename)[0])
entry['description'] = request.POST.get('description')
entry['media_type'] = u'image' # heh
- entry['uploader'] = request.user
+ entry['uploader'] = request.user['_id']
# Save, just so we can get the entry id for the sake of using
# it to generate the file path
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html
index e07cee44..5ccd7299 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html
@@ -22,7 +22,7 @@
{% if media %}
Media details for {{media.uploader.username}}
+ user= media.uploader().username) }}">{{media.uploader.username}}
/ {{media.title}}
@@ -32,7 +32,7 @@
Uploaded on {{ "%4d-%02d-%02d"|format(media.created.year,
media.created.month,media.created.day)}} by {{media.uploader.username}}
+ user= media.uploader().username) }}">{{media.uploader.username}}
Description: {{media.description}}
{% else %}
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index 0d9833cd..41bdb402 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -31,7 +31,7 @@ def user_home(request, page):
return exc.HTTPNotFound()
cursor = request.db.MediaEntry.find(
- {'uploader': user,
+ {'uploader': user['_id'],
'state': 'processed'}).sort('created', DESCENDING)
pagination = Pagination(page, cursor)
--
cgit v1.2.3
From 4194b05d987d8a0dffc1c29d4d3fc706be15b386 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 22 May 2011 16:37:58 -0500
Subject: Forgot switch to media.uploader() in the same way on two lines :P
---
mediagoblin/templates/mediagoblin/user_pages/media.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html
index 5ccd7299..3c781006 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html
@@ -22,7 +22,7 @@
{% if media %}
Media details for {{media.uploader.username}}
+ user= media.uploader().username) }}">{{media.uploader().username}}
/ {{media.title}}
@@ -32,7 +32,7 @@
Uploaded on {{ "%4d-%02d-%02d"|format(media.created.year,
media.created.month,media.created.day)}} by {{media.uploader.username}}
+ user= media.uploader().username) }}">{{media.uploader().username}}
Description: {{media.description}}
{% else %}
--
cgit v1.2.3
From cf0cc3358b2de523013a27af2ce6787e86b3932c Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 22 May 2011 16:40:31 -0500
Subject: Slightly better spacing in media.html
---
.../templates/mediagoblin/user_pages/media.html | 27 ++++++++++++++--------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html
index 3c781006..036bf726 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html
@@ -20,20 +20,27 @@
{# temporarily, an "image gallery" that isn't one really ;) #}
{% if media %}
-
-
- Uploaded on {{ "%4d-%02d-%02d"|format(media.created.year,
- media.created.month,media.created.day)}} by {{media.uploader().username}}
- Description: {{media.description}}
+
+ Uploaded on
+ {{ "%4d-%02d-%02d"|format(media.created.year,
+ media.created.month, media.created.day) }}
+ by
+
+ {{- media.uploader().username }}
+
+ Description: {{ media.description }}
{% else %}
Sorry, no such media found.
--
cgit v1.2.3
From 50c880ac0f0d9fa90244aa8165b53a8968ae3a1a Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 22 May 2011 17:06:11 -0500
Subject: A more explicit version of get_page_url that doesn't use the request
is still an option now ;)
---
mediagoblin/util.py | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index f56bea43..2865cf11 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -351,13 +351,20 @@ class Pagination(object):
yield num
last = num
- def get_page_url(self, request, page_no):
+ def get_page_url_explicit(self, base_url, get_params, page_no):
"""
- Get a new page url based of the request, and the new page number.
+ Get a page url by adding a page= parameter to the base url
"""
- path_info = request.path_info
- get_params = request.GET
new_get_params = copy.copy(get_params or {})
new_get_params['page'] = page_no
return "%s?%s" % (
- path_info, urllib.urlencode(new_get_params))
+ base_url, urllib.urlencode(new_get_params))
+
+ def get_page_url(self, request, page_no):
+ """
+ Get a new page url based of the request, and the new page number.
+
+ This is a nice wrapper around get_page_url_explicit()
+ """
+ return self.get_page_url_explicit(
+ request.path_info, request.GET, page_no)
--
cgit v1.2.3
From f4cfb4e9c8bdfdb3662417048cd6caf2fa4bcd02 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 22 May 2011 17:11:59 -0500
Subject: Encourage users to run migrations every time they buildout.
---
docs/hackinghowto.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/hackinghowto.rst b/docs/hackinghowto.rst
index 3544ec92..a56498bb 100644
--- a/docs/hackinghowto.rst
+++ b/docs/hackinghowto.rst
@@ -96,7 +96,7 @@ While hacking on GNU MediaGoblin over time, you'll eventually have to
update your development environment because the dependencies have
changed. To do that, run::
- ./bin/buildout
+ ./bin/buildout && ./bin/gmg migrate
**Updating for code changes**
--
cgit v1.2.3
From 00c39256145127b9a0f34f4fdc525412065f9426 Mon Sep 17 00:00:00 2001
From: Bernhard Keller
Date: Mon, 23 May 2011 19:00:46 +0200
Subject: modified atomfeed feature, corrected spacing, url generation, routing
id
---
mediagoblin/templates/mediagoblin/base.html | 2 ++
.../templates/mediagoblin/user_pages/user.html | 11 +++++++
mediagoblin/user_pages/routing.py | 4 ++-
mediagoblin/user_pages/views.py | 34 ++++++++++++++++++++++
4 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/templates/mediagoblin/base.html b/mediagoblin/templates/mediagoblin/base.html
index 4b634cf1..c4bc1364 100644
--- a/mediagoblin/templates/mediagoblin/base.html
+++ b/mediagoblin/templates/mediagoblin/base.html
@@ -20,6 +20,8 @@
{% block title %}MediaGoblin{% endblock title %}
+ {% block mediagoblin_head %}
+ {% endblock mediagoblin_head %}
diff --git a/mediagoblin/templates/mediagoblin/user_pages/user.html b/mediagoblin/templates/mediagoblin/user_pages/user.html
index d1809e80..2d09f685 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/user.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/user.html
@@ -16,6 +16,14 @@
# along with this program. If not, see .
#}
{% extends "mediagoblin/base.html" %}
+
+{% block mediagoblin_head %}
+
+{% endblock mediagoblin_head %}
+
{% block mediagoblin_content -%}
{% if user %}
User page for '{{ user.username }}'
@@ -25,6 +33,9 @@
{% include "mediagoblin/utils/object_gallery.html" %}
+ atom feed
{% else %}
{# This *should* not occur as the view makes sure we pass in a user. #}
{% if request.user %}
Welcome {{ request.user['username'] }}! --
--
cgit v1.2.3
From aba81c9f20acd0fa3fd1a31db678fccfba8777d1 Mon Sep 17 00:00:00 2001
From: Elrond
Date: Thu, 26 May 2011 23:09:33 +0200
Subject: Starting "edit" functionality.
This adds a link to the "edit" form, the form, the view for
displaying the form and that's about it.
---
mediagoblin/decorators.py | 20 ++++++++++++
mediagoblin/edit/__init__.py | 0
mediagoblin/edit/forms.py | 27 +++++++++++++++
mediagoblin/edit/routing.py | 22 +++++++++++++
mediagoblin/edit/views.py | 23 +++++++++++++
mediagoblin/routing.py | 2 ++
mediagoblin/templates/mediagoblin/edit/edit.html | 38 ++++++++++++++++++++++
.../templates/mediagoblin/user_pages/media.html | 3 ++
8 files changed, 135 insertions(+)
create mode 100644 mediagoblin/edit/__init__.py
create mode 100644 mediagoblin/edit/forms.py
create mode 100644 mediagoblin/edit/routing.py
create mode 100644 mediagoblin/edit/views.py
create mode 100644 mediagoblin/templates/mediagoblin/edit/edit.html
diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py
index ff3f0b5e..fe631112 100644
--- a/mediagoblin/decorators.py
+++ b/mediagoblin/decorators.py
@@ -99,3 +99,23 @@ def get_user_media_entry(controller):
return controller(request, media=media, *args, **kwargs)
return _make_safe(wrapper, controller)
+
+def get_media_entry_by_id(controller):
+ """
+ Pass in a MediaEntry based off of a url component
+ """
+ def wrapper(request, *args, **kwargs):
+ try:
+ media = request.db.MediaEntry.find_one(
+ {'_id': ObjectId(request.matchdict['media']),
+ 'state': 'processed'})
+ except InvalidId:
+ return exc.HTTPNotFound()
+
+ # Still no media? Okay, 404.
+ if not media:
+ return exc.HTTPNotFound()
+
+ return controller(request, media=media, *args, **kwargs)
+
+ return _make_safe(wrapper, controller)
diff --git a/mediagoblin/edit/__init__.py b/mediagoblin/edit/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/mediagoblin/edit/forms.py b/mediagoblin/edit/forms.py
new file mode 100644
index 00000000..ea25141d
--- /dev/null
+++ b/mediagoblin/edit/forms.py
@@ -0,0 +1,27 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+
+import wtforms
+
+
+class EditForm(wtforms.Form):
+ title = wtforms.TextField(
+ 'Title',
+ [wtforms.validators.Length(min=0, max=500)])
+ slug = wtforms.TextField(
+ 'Slug')
+ description = wtforms.TextAreaField('Description of this work')
diff --git a/mediagoblin/edit/routing.py b/mediagoblin/edit/routing.py
new file mode 100644
index 00000000..d7396a60
--- /dev/null
+++ b/mediagoblin/edit/routing.py
@@ -0,0 +1,22 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+from routes.route import Route
+
+edit_routes = [
+ Route('mediagoblin.edit.edit_media', "/{media}/",
+ controller="mediagoblin.edit.views:edit_media"),
+]
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
new file mode 100644
index 00000000..11dd58be
--- /dev/null
+++ b/mediagoblin/edit/views.py
@@ -0,0 +1,23 @@
+
+
+from webob import Response
+
+from mediagoblin.edit import forms
+from mediagoblin.decorators import require_active_login, get_media_entry_by_id
+
+@get_media_entry_by_id
+@require_active_login
+def edit_media(request, media):
+ form = forms.EditForm(request.POST,
+ title = media['title'],
+ slug = media['slug'],
+ description = media['description'])
+
+ # render
+ template = request.template_env.get_template(
+ 'mediagoblin/edit/edit.html')
+ return Response(
+ template.render(
+ {'request': request,
+ 'media': media,
+ 'form': form}))
diff --git a/mediagoblin/routing.py b/mediagoblin/routing.py
index 356ef678..b854c85a 100644
--- a/mediagoblin/routing.py
+++ b/mediagoblin/routing.py
@@ -19,6 +19,7 @@ from routes import Mapper
from mediagoblin.auth.routing import auth_routes
from mediagoblin.submit.routing import submit_routes
from mediagoblin.user_pages.routing import user_routes
+from mediagoblin.edit.routing import edit_routes
def get_mapper():
mapping = Mapper()
@@ -31,5 +32,6 @@ def get_mapper():
mapping.extend(auth_routes, '/auth')
mapping.extend(submit_routes, '/submit')
mapping.extend(user_routes, '/u')
+ mapping.extend(edit_routes, '/edit')
return mapping
diff --git a/mediagoblin/templates/mediagoblin/edit/edit.html b/mediagoblin/templates/mediagoblin/edit/edit.html
new file mode 100644
index 00000000..72773cb5
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/edit/edit.html
@@ -0,0 +1,38 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% import "/mediagoblin/utils/wtforms.html" as wtforms_util %}
+
+{% block mediagoblin_content %}
+
{% endblock %}
diff --git a/mediagoblin/templates/mediagoblin/utils/wtforms.html b/mediagoblin/templates/mediagoblin/utils/wtforms.html
index 15556936..4a37ab33 100644
--- a/mediagoblin/templates/mediagoblin/utils/wtforms.html
+++ b/mediagoblin/templates/mediagoblin/utils/wtforms.html
@@ -15,6 +15,30 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
#}
+
+{# Auto-render a form as a series of divs #}
+{% macro render_divs(form) -%}
+ {% for field in form %}
+
+
{{ field.label }}
+ {% if field.description -%}
+
{{ field.description }}
+ {%- endif %}
+
{{ field }}
+ {%- if field.errors -%}
+
+
+ {% for error in field.errors %}
+
{{ error }}
+ {% endfor %}
+
+
+ {%- endif %}
+
+ {% endfor %}
+{%- endmacro %}
+
+{# Auto-render a form as a table #}
{% macro render_table(form) -%}
{% for field in form %}
atom feed
--
cgit v1.2.3
From 8bfc87e18e0d3654ddb85b8644002ce6d3610f05 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 29 May 2011 17:49:03 -0500
Subject: Use the object gallery file on the front page also
---
mediagoblin/templates/mediagoblin/root.html | 10 +---------
1 file changed, 1 insertion(+), 9 deletions(-)
diff --git a/mediagoblin/templates/mediagoblin/root.html b/mediagoblin/templates/mediagoblin/root.html
index 05926687..e5344e08 100644
--- a/mediagoblin/templates/mediagoblin/root.html
+++ b/mediagoblin/templates/mediagoblin/root.html
@@ -41,15 +41,7 @@
{# temporarily, an "image gallery" that isn't one really ;) #}
{% endblock %}
--
cgit v1.2.3
From 5866d1a8fbe31709fe21b2c830f7ee3eab7b3775 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Tue, 31 May 2011 19:29:36 -0500
Subject: Give a "proper" view for resending verification email
---
mediagoblin/auth/routing.py | 5 ++++-
mediagoblin/auth/views.py | 15 ++++++++------
.../auth/resent_verification_email.html | 24 ++++++++++++++++++++++
3 files changed, 37 insertions(+), 7 deletions(-)
create mode 100644 mediagoblin/templates/mediagoblin/auth/resent_verification_email.html
diff --git a/mediagoblin/auth/routing.py b/mediagoblin/auth/routing.py
index 069e3019..a8909fbb 100644
--- a/mediagoblin/auth/routing.py
+++ b/mediagoblin/auth/routing.py
@@ -30,4 +30,7 @@ auth_routes = [
Route('mediagoblin.auth.verify_email_notice', '/verification_required/',
controller='mediagoblin.auth.views:verify_email_notice'),
Route('mediagoblin.auth.resend_verification', '/resend_verification/',
- controller='mediagoblin.auth.views:resend_activation')]
+ controller='mediagoblin.auth.views:resend_activation'),
+ Route('mediagoblin.auth.resend_verification_success',
+ '/resend_verification_success/',
+ controller='mediagoblin.auth.views:resend_activation_success')]
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index 22fdd46b..15cd65e5 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -140,6 +140,7 @@ def logout(request):
return exc.HTTPFound(
location=request.urlgen("index"))
+
def verify_email(request):
"""
Email verification view
@@ -183,6 +184,7 @@ def verify_email_notice(request):
template.render(
{'request': request}))
+
def resend_activation(request):
"""
The reactivation view
@@ -215,12 +217,13 @@ def resend_activation(request):
userid=unicode(request.user['_id']),
verification_key=request.user['verification_key'])))
+ return exc.HTTPFound(
+ location=request.urlgen('mediagoblin.auth.resend_verification_success'))
- # TODO: For now, we use the successful registration page until we get a
- # proper messaging system.
+def resend_activation_success(request):
template = request.template_env.get_template(
- 'mediagoblin/auth/register_success.html')
- return exc.HTTPFound(
- location=request.urlgen('mediagoblin.auth.register_success'))
-
+ 'mediagoblin/auth/resent_verification_email.html')
+ return Response(
+ template.render(
+ {'request': request}))
diff --git a/mediagoblin/templates/mediagoblin/auth/resent_verification_email.html b/mediagoblin/templates/mediagoblin/auth/resent_verification_email.html
new file mode 100644
index 00000000..da3a9e99
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/auth/resent_verification_email.html
@@ -0,0 +1,24 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% block mediagoblin_content %}
+
+ Resent your verification email.
+
+{% endblock %}
--
cgit v1.2.3
From a72c504b257c7e2a2c3fec7da67bad5e0f6095be Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Tue, 31 May 2011 19:30:05 -0500
Subject: Just adjusting some spacing so we don't go over 80 chars
---
mediagoblin/decorators.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/mediagoblin/decorators.py b/mediagoblin/decorators.py
index bc12d61c..a5bede54 100644
--- a/mediagoblin/decorators.py
+++ b/mediagoblin/decorators.py
@@ -36,9 +36,11 @@ def require_active_login(controller):
Require an active login from the user.
"""
def new_controller_func(request, *args, **kwargs):
- if request.user and request.user.get('status') == u'needs_email_verification':
+ if request.user and \
+ request.user.get('status') == u'needs_email_verification':
return exc.HTTPFound(
- location = request.urlgen('mediagoblin.auth.verify_email_notice'))
+ location = request.urlgen(
+ 'mediagoblin.auth.verify_email_notice'))
elif not request.user or request.user.get('status') != u'active':
return exc.HTTPFound(
location="%s?next=%s" % (
--
cgit v1.2.3
From 73a1bc85f1beb257169c777452eb878fa7e684a1 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Tue, 31 May 2011 19:31:23 -0500
Subject: Moving import to outside of this function
---
mediagoblin/auth/views.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index 15cd65e5..906d6f13 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -14,6 +14,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
+import bson.objectid
from webob import Response, exc
from mediagoblin.auth import lib as auth_lib
@@ -148,7 +149,6 @@ def verify_email(request):
validates GET parameters against database and unlocks the user account, if
you are lucky :)
"""
- import bson.objectid
user = request.db.User.find_one(
{'_id': bson.objectid.ObjectId(unicode(request.GET.get('userid')))})
--
cgit v1.2.3
From 155f24f9f5ac1c944addddf84c7a129d55f63263 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Tue, 31 May 2011 19:37:28 -0500
Subject: If a user doesn't provide a userid and a token to the verify_email
function, might as well 404
---
mediagoblin/auth/views.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index 906d6f13..4ccd3d86 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -149,12 +149,16 @@ def verify_email(request):
validates GET parameters against database and unlocks the user account, if
you are lucky :)
"""
+ # If we don't have userid and token parameters, we can't do anything; 404
+ if not request.GET.has_key('userid') or not request.GET.has_key('token'):
+ return exc.HTTPNotFound()
+
user = request.db.User.find_one(
- {'_id': bson.objectid.ObjectId(unicode(request.GET.get('userid')))})
+ {'_id': bson.objectid.ObjectId(unicode(request.GET['userid']))})
verification_successful = bool
- if user and user['verification_key'] == unicode(request.GET.get('token')):
+ if user and user['verification_key'] == unicode(request.GET['token']):
user['status'] = u'active'
user['email_verified'] = True
verification_successful = True
--
cgit v1.2.3
From 4d4b49a84e2791da6b12ef580565251c379264b6 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Tue, 31 May 2011 19:54:26 -0500
Subject: 0.0.2 of GNU MediaGoblin!
---
setup.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/setup.py b/setup.py
index 752f1b57..097dd7f2 100644
--- a/setup.py
+++ b/setup.py
@@ -18,7 +18,7 @@ from setuptools import setup, find_packages
setup(
name = "mediagoblin",
- version = "0.0.1",
+ version = "0.0.2",
packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
zip_safe=False,
# scripts and dependencies
@@ -45,7 +45,7 @@ setup(
test_suite='nose.collector',
license = 'AGPLv3',
- author = 'Christopher Webber',
+ author = 'Free Software Foundation and contributors',
author_email = 'cwebber@gnu.org',
entry_points = """\
[console_scripts]
--
cgit v1.2.3
From c849e690925cb656b8c00ccbeda12aeab22c2fdd Mon Sep 17 00:00:00 2001
From: Elrond
Date: Thu, 2 Jun 2011 14:25:31 +0200
Subject: Check for edit permission.
You need to own the media, or be an admin to use the edit form.
As simple as that, for now.
---
mediagoblin/edit/views.py | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
index 050ece4e..e5dccc81 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -5,9 +5,22 @@ from webob import Response, exc
from mediagoblin.edit import forms
from mediagoblin.decorators import require_active_login, get_media_entry_by_id
+
+def may_edit_media(request, media):
+ """Check, if the request's user may edit the media details"""
+ if media['uploader'] == request.user['_id']:
+ return True
+ if request.user['is_admin']:
+ return True
+ return False
+
+
@get_media_entry_by_id
@require_active_login
def edit_media(request, media):
+ if not may_edit_media(request, media):
+ return exc.HTTPForbidden()
+
form = forms.EditForm(request.POST,
title = media['title'],
slug = media['slug'],
--
cgit v1.2.3
From e0f8487005f4e9adca41648d35bb8dc6db850032 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 2 Jun 2011 08:47:30 -0500
Subject: Elrond put that ObjectId thing in the db.util module and wants us to
use that one ;)
---
mediagoblin/auth/views.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index 4ccd3d86..0c125544 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -14,9 +14,9 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-import bson.objectid
from webob import Response, exc
+from mediagoblin.db.util import ObjectId
from mediagoblin.auth import lib as auth_lib
from mediagoblin.auth import forms as auth_forms
from mediagoblin.util import send_email
@@ -154,7 +154,7 @@ def verify_email(request):
return exc.HTTPNotFound()
user = request.db.User.find_one(
- {'_id': bson.objectid.ObjectId(unicode(request.GET['userid']))})
+ {'_id': ObjectId(unicode(request.GET['userid']))})
verification_successful = bool
--
cgit v1.2.3
From a77d952aa6659f0291f856495b18a43dd7e28508 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 2 Jun 2011 09:02:13 -0500
Subject: No need for a method for generating the verification key as a method
on the class, can just do that in the view
---
mediagoblin/auth/views.py | 6 ++++--
mediagoblin/db/models.py | 8 --------
2 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index 0c125544..e9d75f8b 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -14,6 +14,8 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
+import uuid
+
from webob import Response, exc
from mediagoblin.db.util import ObjectId
@@ -195,8 +197,8 @@ def resend_activation(request):
Resend the activation email.
"""
-
- request.user.generate_new_verification_key()
+ request.user['verification_key'] = unicode(uuid.uuid4())
+ request.user.save()
# Copied shamelessly from the register view above.
diff --git a/mediagoblin/db/models.py b/mediagoblin/db/models.py
index 0b85430a..3da97a49 100644
--- a/mediagoblin/db/models.py
+++ b/mediagoblin/db/models.py
@@ -64,14 +64,6 @@ class User(Document):
return auth_lib.bcrypt_check_password(
password, self['pw_hash'])
- def generate_new_verification_key(self):
- """
- Create a new verification key, overwriting the old one.
- """
-
- self['verification_key'] = unicode(uuid.uuid4())
- self.save(validate=False)
-
class MediaEntry(Document):
__collection__ = 'media_entries'
--
cgit v1.2.3
From b897fdf91b2fe03c299880545fc6712d50cd0e97 Mon Sep 17 00:00:00 2001
From: Elrond
Date: Thu, 2 Jun 2011 16:39:47 +0200
Subject: Change edit form to use divs instead of table
---
mediagoblin/templates/mediagoblin/edit/edit.html | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/mediagoblin/templates/mediagoblin/edit/edit.html b/mediagoblin/templates/mediagoblin/edit/edit.html
index bd85f361..d694ce25 100644
--- a/mediagoblin/templates/mediagoblin/edit/edit.html
+++ b/mediagoblin/templates/mediagoblin/edit/edit.html
@@ -25,13 +25,12 @@
-
- {{ wtforms_util.render_table(form) }}
-
-
-
-
-
+
+ {{ wtforms_util.render_divs(form) }}
+
+
+
+
--
cgit v1.2.3
From 8cd5d4f8c3de634905651b1d1e8cd1355b7f3a99 Mon Sep 17 00:00:00 2001
From: Elrond
Date: Thu, 2 Jun 2011 16:48:15 +0200
Subject: Prepare for moving /edit/ under /u/.../edit/
To make moving the whole thing under /u/ easier, prepare to
pass in the {user} needed for that.
---
mediagoblin/edit/routing.py | 2 +-
mediagoblin/edit/views.py | 4 ++--
mediagoblin/templates/mediagoblin/edit/edit.html | 1 +
mediagoblin/templates/mediagoblin/user_pages/media.html | 1 +
4 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/mediagoblin/edit/routing.py b/mediagoblin/edit/routing.py
index d7396a60..54f2661a 100644
--- a/mediagoblin/edit/routing.py
+++ b/mediagoblin/edit/routing.py
@@ -17,6 +17,6 @@
from routes.route import Route
edit_routes = [
- Route('mediagoblin.edit.edit_media', "/{media}/",
+ Route('mediagoblin.edit.edit_media', "/{user}/{media}/",
controller="mediagoblin.edit.views:edit_media"),
]
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
index e5dccc81..a0afaa30 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -3,7 +3,7 @@
from webob import Response, exc
from mediagoblin.edit import forms
-from mediagoblin.decorators import require_active_login, get_media_entry_by_id
+from mediagoblin.decorators import require_active_login, get_user_media_entry
def may_edit_media(request, media):
@@ -15,7 +15,7 @@ def may_edit_media(request, media):
return False
-@get_media_entry_by_id
+@get_user_media_entry
@require_active_login
def edit_media(request, media):
if not may_edit_media(request, media):
diff --git a/mediagoblin/templates/mediagoblin/edit/edit.html b/mediagoblin/templates/mediagoblin/edit/edit.html
index d694ce25..295d57eb 100644
--- a/mediagoblin/templates/mediagoblin/edit/edit.html
+++ b/mediagoblin/templates/mediagoblin/edit/edit.html
@@ -23,6 +23,7 @@
--
cgit v1.2.3
From 0732236e9c816dd2b04f5a9e97632a861de225ad Mon Sep 17 00:00:00 2001
From: Elrond
Date: Thu, 2 Jun 2011 17:43:54 +0200
Subject: Handle Exceptions from save(); Move may_edit_media
Turn .save() excpetions into a HTTPConflict. Not nice, but
at least the user gets the error. Until there is a proper
way to validate things and get nice errors.
Move may_edit_media() to lib.py, as it's not a view.
---
mediagoblin/edit/lib.py | 8 ++++++++
mediagoblin/edit/views.py | 15 +++++----------
2 files changed, 13 insertions(+), 10 deletions(-)
create mode 100644 mediagoblin/edit/lib.py
diff --git a/mediagoblin/edit/lib.py b/mediagoblin/edit/lib.py
new file mode 100644
index 00000000..293a0547
--- /dev/null
+++ b/mediagoblin/edit/lib.py
@@ -0,0 +1,8 @@
+
+def may_edit_media(request, media):
+ """Check, if the request's user may edit the media details"""
+ if media['uploader'] == request.user['_id']:
+ return True
+ if request.user['is_admin']:
+ return True
+ return False
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
index a0afaa30..b8e28e29 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -3,18 +3,10 @@
from webob import Response, exc
from mediagoblin.edit import forms
+from mediagoblin.edit.lib import may_edit_media
from mediagoblin.decorators import require_active_login, get_user_media_entry
-def may_edit_media(request, media):
- """Check, if the request's user may edit the media details"""
- if media['uploader'] == request.user['_id']:
- return True
- if request.user['is_admin']:
- return True
- return False
-
-
@get_user_media_entry
@require_active_login
def edit_media(request, media):
@@ -30,7 +22,10 @@ def edit_media(request, media):
media['title'] = request.POST['title']
media['description'] = request.POST['description']
media['slug'] = request.POST['slug']
- media.save()
+ try:
+ media.save()
+ except Exception as e:
+ return exc.HTTPConflict(detail = str(e))
# redirect
return exc.HTTPFound(
--
cgit v1.2.3
From 5603d4df8fcf1a7a5b85906dad0049d7e79cce6c Mon Sep 17 00:00:00 2001
From: Jakob Kramer
Date: Thu, 2 Jun 2011 17:35:20 +0200
Subject: should fix #324
---
mediagoblin/submit/security.py | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 mediagoblin/submit/security.py
diff --git a/mediagoblin/submit/security.py b/mediagoblin/submit/security.py
new file mode 100644
index 00000000..db4c860d
--- /dev/null
+++ b/mediagoblin/submit/security.py
@@ -0,0 +1,32 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+from mimetypes import guess_type
+
+from Image import open as image_open
+
+ALLOWED = ['image/jpeg', 'image/png', 'image/tiff', 'image/gif']
+
+def check_filetype(posted_file):
+ if not guess_type(posted_file.filename) in ALLOWED:
+ return False
+
+ try:
+ image = image_open(posted_file.file)
+ except IOError:
+ return False
+
+ return True
--
cgit v1.2.3
From 3eeadc922a669af9b4df4a41dc464bf6587802c1 Mon Sep 17 00:00:00 2001
From: Jakob Kramer
Date: Thu, 2 Jun 2011 17:47:38 +0200
Subject: add changes in mediagoblin/submit/views.py
---
mediagoblin/submit/views.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 262f2b12..5ddf992f 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -21,7 +21,7 @@ from webob import Response, exc
from werkzeug.utils import secure_filename
from mediagoblin.decorators import require_active_login
-from mediagoblin.submit import forms as submit_forms
+from mediagoblin.submit import forms as submit_forms, security
from mediagoblin.process_media import process_media_initial
@@ -38,6 +38,9 @@ def submit_start(request):
and request.POST['file'].file):
submit_form.file.errors.append(
u'You must provide a file.')
+ elif not security.check_filetype(request.POST['file']):
+ submit_form.file.errors.append(
+ u'The file doesn\'t seem to be an image!')
else:
filename = request.POST['file'].filename
--
cgit v1.2.3
From 9bfe1d8e12c77d7a47049bffaa694441abd71489 Mon Sep 17 00:00:00 2001
From: Elrond
Date: Thu, 2 Jun 2011 18:28:26 +0200
Subject: Add GNU headers to new *.py
---
mediagoblin/edit/lib.py | 16 ++++++++++++++++
mediagoblin/edit/views.py | 15 +++++++++++++++
2 files changed, 31 insertions(+)
diff --git a/mediagoblin/edit/lib.py b/mediagoblin/edit/lib.py
index 293a0547..2a810349 100644
--- a/mediagoblin/edit/lib.py
+++ b/mediagoblin/edit/lib.py
@@ -1,3 +1,19 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
def may_edit_media(request, media):
"""Check, if the request's user may edit the media details"""
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
index b8e28e29..7df47b18 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -1,3 +1,18 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
from webob import Response, exc
--
cgit v1.2.3
From 69dadf429d10e1719d932acde071425739218085 Mon Sep 17 00:00:00 2001
From: Jef van Schendel
Date: Thu, 2 Jun 2011 22:44:34 +0200
Subject: Right-aligned input buttons, added gradient
---
mediagoblin/static/css/base.css | 35 ++++++++++++++++++++++-------------
1 file changed, 22 insertions(+), 13 deletions(-)
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index 1092dccf..153e5ab0 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -69,34 +69,39 @@ a.mediagoblin_logo:hover {
float:right;
}
+/* common website elements */
+
+.dotted_line {
+ width:100%;
+ height:0px;
+ border-bottom: dotted 1px #5f5f5f;
+ position:absolute;
+ left:0px;
+ margin-top:-20px;
+}
+
.button {
font-family:'Carter One', arial, serif;
height:32px;
min-width:99px;
background-color:#86d4b1;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#86d4b1), to(#62caa2));
+ background-image: -webkit-linear-gradient(top, #86d4b1, #62caa2);
+ background-image: -moz-linear-gradient(top, #86d4b1, #62caa2);
+ background-image: -ms-linear-gradient(top, #86d4b1, #62caa2);
+ background-image: -o-linear-gradient(top, #86d4b1, #62caa2);
+ background-image: linear-gradient(top, #86d4b1, #62caa2);
box-shadow:0px 0px 4px #000;
border-radius:5px;
border:none;
color:#272727;
- margin:10px;
+ margin:10px 0px;
font-size:1em;
- display:block;
text-align:center;
padding-left:11px;
padding-right:11px;
}
-/* common website elements */
-
-.dotted_line {
- width:100%;
- height:0px;
- border-bottom: dotted 1px #5f5f5f;
- position:absolute;
- left:0px;
- margin-top:-20px;
-}
-
/* forms */
.form_box {
@@ -139,6 +144,10 @@ a.mediagoblin_logo:hover {
margin-bottom:8px;
}
+.form_submit_buttons {
+ text-align:right;
+}
+
/* media pages */
img.media_image {
--
cgit v1.2.3
From 3e965450953e643afa9252feedb60f3a4c849c9d Mon Sep 17 00:00:00 2001
From: Jef van Schendel
Date: Thu, 2 Jun 2011 22:57:10 +0200
Subject: Added lines background to forms
---
mediagoblin/static/css/base.css | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/mediagoblin/static/css/base.css b/mediagoblin/static/css/base.css
index 153e5ab0..e9f2c4a9 100644
--- a/mediagoblin/static/css/base.css
+++ b/mediagoblin/static/css/base.css
@@ -109,8 +109,9 @@ a.mediagoblin_logo:hover {
margin-left:auto;
margin-right:auto;
background-color:#393939;
- padding:0px 83px 30px 83px;
- border-top:5px solid #d49086;
+ background-image:url("../images/background_lines.png");
+ background-repeat:repeat-x;
+ padding:1px 83px 30px 83px;
font-size:18px;
}
--
cgit v1.2.3
From f80cdc586840f845b1163e935588d2810d295793 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 2 Jun 2011 16:04:17 -0500
Subject: No reason for 'verification_successful = bool' here.
---
mediagoblin/auth/views.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index e9d75f8b..948db188 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -158,8 +158,6 @@ def verify_email(request):
user = request.db.User.find_one(
{'_id': ObjectId(unicode(request.GET['userid']))})
- verification_successful = bool
-
if user and user['verification_key'] == unicode(request.GET['token']):
user['status'] = u'active'
user['email_verified'] = True
--
cgit v1.2.3
From 04cb99b22316a9d7d93e30e4748d74d51fa63c85 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 2 Jun 2011 16:30:06 -0500
Subject: attribute values should be quoted :)
---
mediagoblin/templates/mediagoblin/utils/pagination.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/templates/mediagoblin/utils/pagination.html b/mediagoblin/templates/mediagoblin/utils/pagination.html
index 5ca5e09b..62e8af91 100644
--- a/mediagoblin/templates/mediagoblin/utils/pagination.html
+++ b/mediagoblin/templates/mediagoblin/utils/pagination.html
@@ -32,7 +32,7 @@
{{ page }}
{% endif %}
{% else %}
- …
+ …
{% endif %}
{%- endfor %}
--
cgit v1.2.3
From 02d80437d1cdda5b2a8596d024aafa8b286cb360 Mon Sep 17 00:00:00 2001
From: Aleksandar Micovic
Date: Thu, 2 Jun 2011 21:07:37 -0400
Subject: Refactored the sending of verification emails.
---
mediagoblin/auth/lib.py | 34 ++++++++++++++++++++++++++++++++
mediagoblin/auth/views.py | 50 +++++------------------------------------------
2 files changed, 39 insertions(+), 45 deletions(-)
diff --git a/mediagoblin/auth/lib.py b/mediagoblin/auth/lib.py
index 7cf021bc..dc5f9941 100644
--- a/mediagoblin/auth/lib.py
+++ b/mediagoblin/auth/lib.py
@@ -19,6 +19,9 @@ import random
import bcrypt
+from mediagoblin.util import send_email
+from mediagoblin import globals as mgoblin_globals
+
def bcrypt_check_password(raw_pass, stored_hash, extra_salt=None):
"""
@@ -84,3 +87,34 @@ def fake_login_attempt():
randplus_hashed_pass = bcrypt.hashpw(hashed_pass, rand_salt)
randplus_stored_hash == randplus_hashed_pass
+
+
+def send_verification_email(user, request):
+ """
+ Send the verification email to users to activate their accounts.
+
+ Args:
+ - user: a user object
+ - request: the request
+ """
+
+ email_template = request.template_env.get_template(
+ 'mediagoblin/auth/verification_email.txt')
+
+ # TODO: There is no error handling in place
+ send_email(
+ mgoblin_globals.email_sender_address,
+ [user['email']],
+ # TODO
+ # Due to the distributed nature of GNU MediaGoblin, we should
+ # find a way to send some additional information about the
+ # specific GNU MediaGoblin instance in the subject line. For
+ # example "GNU MediaGoblin @ Wandborg - [...]".
+ 'GNU MediaGoblin - Verify your email!',
+ email_template.render(
+ username=user['username'],
+ verification_url='http://{host}{uri}?userid={userid}&token={verification_key}'.format(
+ host=request.host,
+ uri=request.urlgen('mediagoblin.auth.verify_email'),
+ userid=unicode(user['_id']),
+ verification_key=user['verification_key'])))
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index 948db188..e4f1a7b1 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -21,8 +21,7 @@ from webob import Response, exc
from mediagoblin.db.util import ObjectId
from mediagoblin.auth import lib as auth_lib
from mediagoblin.auth import forms as auth_forms
-from mediagoblin.util import send_email
-from mediagoblin import globals as mgoblin_globals
+from mediagoblin.auth.lib import send_verification_email
def register(request):
@@ -52,27 +51,8 @@ def register(request):
request.POST['password'])
entry.save(validate=True)
- email_template = request.template_env.get_template(
- 'mediagoblin/auth/verification_email.txt')
-
- # TODO: There is no error handling in place
- send_email(
- mgoblin_globals.email_sender_address,
- [entry['email']],
- # TODO
- # Due to the distributed nature of GNU MediaGoblin, we should
- # find a way to send some additional information about the
- # specific GNU MediaGoblin instance in the subject line. For
- # example "GNU MediaGoblin @ Wandborg - [...]".
- 'GNU MediaGoblin - Verify email',
- email_template.render(
- username=entry['username'],
- verification_url='http://{host}{uri}?userid={userid}&token={verification_key}'.format(
- host=request.host,
- uri=request.urlgen('mediagoblin.auth.verify_email'),
- userid=unicode(entry['_id']),
- verification_key=entry['verification_key'])))
-
+ send_verification_email(entry, request)
+
# Redirect to register_success
return exc.HTTPFound(
location=request.urlgen("mediagoblin.auth.register_success"))
@@ -195,31 +175,11 @@ def resend_activation(request):
Resend the activation email.
"""
+
request.user['verification_key'] = unicode(uuid.uuid4())
request.user.save()
- # Copied shamelessly from the register view above.
-
- email_template = request.template_env.get_template(
- 'mediagoblin/auth/verification_email.txt')
-
- # TODO: There is no error handling in place
- send_email(
- mgoblin_globals.email_sender_address,
- [request.user['email']],
- # TODO
- # Due to the distributed nature of GNU MediaGoblin, we should
- # find a way to send some additional information about the
- # specific GNU MediaGoblin instance in the subject line. For
- # example "GNU MediaGoblin @ Wandborg - [...]".
- 'GNU MediaGoblin - Verify email',
- email_template.render(
- username=request.user['username'],
- verification_url='http://{host}{uri}?userid={userid}&token={verification_key}'.format(
- host=request.host,
- uri=request.urlgen('mediagoblin.auth.verify_email'),
- userid=unicode(request.user['_id']),
- verification_key=request.user['verification_key'])))
+ send_verification_email(request.user, request)
return exc.HTTPFound(
location=request.urlgen('mediagoblin.auth.resend_verification_success'))
--
cgit v1.2.3
From 55c74e1e4b36d56c1f3c8e69a4cbea43843093c8 Mon Sep 17 00:00:00 2001
From: Elrond
Date: Fri, 3 Jun 2011 23:54:33 +0200
Subject: Propagate Exceptions up in Celery-Eager-Mode
When running in celery-eager mode, the celery machinery
hides all exceptions inside "celery tasks" (you can find
out about them on the task handle somehow). Currently much
better to propagate them straight up, so they're visible on
the console.
---
mediagoblin/celery_setup/__init__.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/mediagoblin/celery_setup/__init__.py b/mediagoblin/celery_setup/__init__.py
index 1a77cc62..d4f25b07 100644
--- a/mediagoblin/celery_setup/__init__.py
+++ b/mediagoblin/celery_setup/__init__.py
@@ -140,6 +140,7 @@ def setup_celery_from_config(app_config, global_config,
if force_celery_always_eager:
celery_settings['CELERY_ALWAYS_EAGER'] = True
+ celery_settings['CELERY_EAGER_PROPAGATES_EXCEPTIONS'] = True
__import__(settings_module)
this_module = sys.modules[settings_module]
--
cgit v1.2.3
From d5e90fe4b487e86261331fab0f7c08f12462625d Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 3 Jun 2011 18:43:08 -0500
Subject: Find out if such a slug exists via a query instead of via a .save()
call
---
mediagoblin/edit/views.py | 31 +++++++++++++++++++------------
1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
index 7df47b18..5cfb2297 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -34,18 +34,25 @@ def edit_media(request, media):
description = media['description'])
if request.method == 'POST' and form.validate():
- media['title'] = request.POST['title']
- media['description'] = request.POST['description']
- media['slug'] = request.POST['slug']
- try:
- media.save()
- except Exception as e:
- return exc.HTTPConflict(detail = str(e))
-
- # redirect
- return exc.HTTPFound(
- location=request.urlgen("mediagoblin.user_pages.media_home",
- user=media.uploader()['username'], media=media['_id']))
+ # Make sure there isn't already a MediaEntry with such a slug
+ # and userid.
+ existing_user_slug_entries = request.db.MediaEntry.find(
+ {'slug': request.POST['slug'],
+ 'uploader': media['uploader'],
+ '_id': {'$ne': media['_id']}}).count()
+
+ if existing_user_slug_entries:
+ form.slug.errors.append(
+ u'An entry with that slug already exists for this user.')
+ else:
+ media['title'] = request.POST['title']
+ media['description'] = request.POST['description']
+ media['slug'] = request.POST['slug']
+
+ # redirect
+ return exc.HTTPFound(
+ location=request.urlgen("mediagoblin.user_pages.media_home",
+ user=media.uploader()['username'], media=media['_id']))
# render
template = request.template_env.get_template(
--
cgit v1.2.3
From c042bc6e218e99f93c1e642b1d77839ca0f4b1f9 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Fri, 3 Jun 2011 18:47:22 -0500
Subject: Title first and foremost... anything else looks weird to me.
---
mediagoblin/templates/mediagoblin/user_pages/media.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mediagoblin/templates/mediagoblin/user_pages/media.html b/mediagoblin/templates/mediagoblin/user_pages/media.html
index 406fd3f6..200f13cd 100644
--- a/mediagoblin/templates/mediagoblin/user_pages/media.html
+++ b/mediagoblin/templates/mediagoblin/user_pages/media.html
@@ -20,11 +20,11 @@
{# temporarily, an "image gallery" that isn't one really ;) #}
{% if media %}
-
{{media.title}}
+
{{ media.description }}
Uploaded on
{{ "%4d-%02d-%02d"|format(media.created.year,
--
cgit v1.2.3
From 747623cc04d58d17595cab318ef4a190de60088d Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 4 Jun 2011 07:41:31 -0500
Subject: I shouldn't have removed the .save() entirely :)
---
mediagoblin/edit/views.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
index 5cfb2297..c3aedac9 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -48,6 +48,7 @@ def edit_media(request, media):
media['title'] = request.POST['title']
media['description'] = request.POST['description']
media['slug'] = request.POST['slug']
+ media.save()
# redirect
return exc.HTTPFound(
--
cgit v1.2.3
From 8ee83b43331bbe4c9d45554178dfa6c98f4f10ab Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 4 Jun 2011 08:48:17 -0500
Subject: Let's redirect back to the media homepage using the slug instead of
the id
---
mediagoblin/edit/views.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
index c3aedac9..0e0faa53 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -53,7 +53,7 @@ def edit_media(request, media):
# redirect
return exc.HTTPFound(
location=request.urlgen("mediagoblin.user_pages.media_home",
- user=media.uploader()['username'], media=media['_id']))
+ user=media.uploader()['username'], media=media['slug']))
# render
template = request.template_env.get_template(
--
cgit v1.2.3
From a1556d3f496efe3fe37cdf474c611af97ab82426 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 4 Jun 2011 08:48:51 -0500
Subject: Mount media editing under /u/{username}/m/{media}/edit/
---
mediagoblin/edit/routing.py | 4 ++--
mediagoblin/user_pages/routing.py | 2 ++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/mediagoblin/edit/routing.py b/mediagoblin/edit/routing.py
index 54f2661a..bf0b2498 100644
--- a/mediagoblin/edit/routing.py
+++ b/mediagoblin/edit/routing.py
@@ -14,9 +14,9 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
+
from routes.route import Route
edit_routes = [
- Route('mediagoblin.edit.edit_media', "/{user}/{media}/",
- controller="mediagoblin.edit.views:edit_media"),
+ # Media editing view handled in user_pages/routing.py
]
diff --git a/mediagoblin/user_pages/routing.py b/mediagoblin/user_pages/routing.py
index 96f97427..c5e9a984 100644
--- a/mediagoblin/user_pages/routing.py
+++ b/mediagoblin/user_pages/routing.py
@@ -22,5 +22,7 @@ user_routes = [
Route('mediagoblin.user_pages.media_home', '/{user}/m/{media}/',
requirements=dict(m_id="[0-9a-fA-F]{24}"),
controller="mediagoblin.user_pages.views:media_home"),
+ Route('mediagoblin.edit.edit_media', "/{user}/m/{media}/edit/",
+ controller="mediagoblin.edit.views:edit_media"),
Route('mediagoblin.user_pages.atom_feed', '/{user}/atom/',
controller="mediagoblin.user_pages.views:atom_feed")]
--
cgit v1.2.3
From c5678c1ab3deb3f7a2961225c35260d5bbd69604 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 4 Jun 2011 13:20:48 -0500
Subject: Proper webtest infrastructure... seems to be about right anyway :)
---
mediagoblin/app.py | 13 ++---
mediagoblin/celery_setup/from_tests.py | 43 ++++++++++++++++
mediagoblin/tests/mgoblin_test_app.ini | 46 +++++++++++++++++
mediagoblin/tests/tools.py | 94 ++++++++++++++++++++++++++++++++++
mediagoblin/util.py | 33 ++++++++++--
setup.py | 1 +
6 files changed, 220 insertions(+), 10 deletions(-)
create mode 100644 mediagoblin/celery_setup/from_tests.py
create mode 100644 mediagoblin/tests/mgoblin_test_app.ini
create mode 100644 mediagoblin/tests/tools.py
diff --git a/mediagoblin/app.py b/mediagoblin/app.py
index 714404de..e5949531 100644
--- a/mediagoblin/app.py
+++ b/mediagoblin/app.py
@@ -139,12 +139,13 @@ def paste_app_factory(global_config, **app_config):
raise ImproperlyConfigured(
"One of direct_remote_path or direct_remote_paths must be provided")
- if asbool(os.environ.get('CELERY_ALWAYS_EAGER')):
- setup_celery_from_config(
- app_config, global_config,
- force_celery_always_eager=True)
- else:
- setup_celery_from_config(app_config, global_config)
+ if not asbool(app_config.get('celery_setup_elsewhere')):
+ if asbool(os.environ.get('CELERY_ALWAYS_EAGER')):
+ setup_celery_from_config(
+ app_config, global_config,
+ force_celery_always_eager=True)
+ else:
+ setup_celery_from_config(app_config, global_config)
mgoblin_app = MediaGoblinApp(
connection, db,
diff --git a/mediagoblin/celery_setup/from_tests.py b/mediagoblin/celery_setup/from_tests.py
new file mode 100644
index 00000000..fe7d7314
--- /dev/null
+++ b/mediagoblin/celery_setup/from_tests.py
@@ -0,0 +1,43 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import os
+
+from mediagoblin.tests.tools import TEST_APP_CONFIG
+from mediagoblin import util
+from mediagoblin.celery_setup import setup_celery_from_config
+from mediagoblin.globals import setup_globals
+
+
+OUR_MODULENAME = 'mediagoblin.celery_setup.from_tests'
+
+
+def setup_self(setup_globals_func=setup_globals):
+ """
+ Set up celery for testing's sake, which just needs to set up
+ celery and celery only.
+ """
+ mgoblin_conf = util.read_config_file(TEST_APP_CONFIG)
+ mgoblin_section = mgoblin_conf['app:mediagoblin']
+
+ setup_celery_from_config(
+ mgoblin_section, mgoblin_conf,
+ settings_module=OUR_MODULENAME,
+ set_environ=False)
+
+
+if os.environ.get('CELERY_CONFIG_MODULE') == OUR_MODULENAME:
+ setup_self()
diff --git a/mediagoblin/tests/mgoblin_test_app.ini b/mediagoblin/tests/mgoblin_test_app.ini
new file mode 100644
index 00000000..abed2615
--- /dev/null
+++ b/mediagoblin/tests/mgoblin_test_app.ini
@@ -0,0 +1,46 @@
+[DEFAULT]
+debug = true
+
+[composite:main]
+use = egg:Paste#urlmap
+/ = mediagoblin
+/mgoblin_media/ = publicstore_serve
+/mgoblin_static/ = mediagoblin_static
+
+[app:mediagoblin]
+use = egg:mediagoblin#app
+filter-with = beaker
+queuestore_base_dir = %(here)s/test_user_dev/media/queue
+publicstore_base_dir = %(here)s/test_user_dev/media/public
+publicstore_base_url = /mgoblin_media/
+direct_remote_path = /mgoblin_static/
+email_sender_address = "notice@mediagoblin.example.org"
+email_debug_mode = true
+db_name = __mediagoblin_tests__
+# Celery shouldn't be set up by the paste app factory as it's set up
+# elsewhere
+celery_setup_elsewhere = true
+
+[app:publicstore_serve]
+use = egg:Paste#static
+document_root = %(here)s/user_dev/media/public
+
+[app:mediagoblin_static]
+use = egg:Paste#static
+document_root = %(here)s/mediagoblin/static/
+
+[filter:beaker]
+use = egg:Beaker#beaker_session
+cache_dir = %(here)s/test_user_dev/beaker
+beaker.session.key = mediagoblin
+# beaker.session.secret = somesupersecret
+beaker.session.data_dir = %(here)s/test_user_dev/beaker/sessions/data
+beaker.session.lock_dir = %(here)s/test_user_dev/beaker/sessions/lock
+
+[celery]
+celery_always_eager = true
+
+[server:main]
+use = egg:Paste#http
+host = 127.0.0.1
+port = 6543
diff --git a/mediagoblin/tests/tools.py b/mediagoblin/tests/tools.py
new file mode 100644
index 00000000..70b74b89
--- /dev/null
+++ b/mediagoblin/tests/tools.py
@@ -0,0 +1,94 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+
+import pkg_resources
+import os, shutil
+
+from paste.deploy import appconfig
+from webtest import TestApp
+
+from mediagoblin import app
+from mediagoblin.db.open import setup_connection_and_db_from_config
+
+
+MEDIAGOBLIN_TEST_DB_NAME = '__mediagoblinunittests__'
+TEST_APP_CONFIG = pkg_resources.resource_filename(
+ 'mediagoblin.tests', 'mgoblin_test_app.ini')
+TEST_USER_DEV = pkg_resources.resource_filename(
+ 'mediagoblin.tests', 'test_user_dev')
+MGOBLIN_APP = None
+
+USER_DEV_DIRECTORIES_TO_SETUP = [
+ 'media/public', 'media/queue',
+ 'beaker/sessions/data', 'beaker/sessions/lock']
+
+
+class BadCeleryEnviron(Exception): pass
+
+
+def get_test_app(dump_old_app=True):
+ if not os.environ.get('CELERY_CONFIG_MODULE') == \
+ 'mediagoblin.celery_setup.from_tests':
+ raise BadCeleryEnviron(
+ u"Sorry, you *absolutely* must run nosetests with the\n"
+ u"mediagoblin.celery_setup.from_tests module. Like so:\n"
+ u"$ CELERY_CONFIG_MODULE=mediagoblin.celery_setup.from_tests ./bin/nosetests")
+
+ # Just return the old app if that exists and it's okay to set up
+ # and return
+ if MGOBLIN_APP and not dump_old_app:
+ return MGOBLIN_APP
+
+ # Remove and reinstall user_dev directories
+ if os.path.exists(TEST_USER_DEV):
+ shutil.rmtree(TEST_USER_DEV)
+
+ for directory in USER_DEV_DIRECTORIES_TO_SETUP:
+ full_dir = os.path.join(TEST_USER_DEV, directory)
+ os.makedirs(full_dir)
+
+ # Get app config
+ config = appconfig(
+ 'config:' + os.path.basename(TEST_APP_CONFIG),
+ relative_to=os.path.dirname(TEST_APP_CONFIG),
+ name='mediagoblin')
+
+ # Wipe database
+ # @@: For now we're dropping collections, but we could also just
+ # collection.remove() ?
+ connection, db = setup_connection_and_db_from_config(
+ config.local_conf)
+
+ collections_to_wipe = [
+ collection
+ for collection in db.collection_names()
+ if not collection.startswith('system.')]
+
+ for collection in collections_to_wipe:
+ db.drop_collection(collection)
+
+ # Don't need these anymore...
+ del(connection)
+ del(db)
+
+ # TODO: Drop and recreate indexes
+
+ # setup app and return
+ test_app = app.paste_app_factory(
+ config.global_conf, **config.local_conf)
+
+ return TestApp(test_app)
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index 2865cf11..fdb2c3f5 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -18,17 +18,20 @@ from email.MIMEText import MIMEText
import gettext
import pkg_resources
import smtplib
+import os
import sys
import re
+import urllib
+from math import ceil
+import copy
+
import jinja2
-from mediagoblin.db.util import ObjectId
import translitcodec
+from paste.deploy.loadwsgi import NicerConfigParser
from mediagoblin import globals as mgoblin_globals
+from mediagoblin.db.util import ObjectId
-import urllib
-from math import ceil
-import copy
TESTS_ENABLED = False
def _activate_testing():
@@ -278,6 +281,28 @@ def get_locale_from_request(request):
return locale_to_lower_upper(target_lang)
+def read_config_file(conf_file):
+ """
+ Read a paste deploy style config file and process it.
+ """
+ if not os.path.exists(conf_file):
+ raise IOError(
+ "MEDIAGOBLIN_CONFIG not set or file does not exist")
+
+ parser = NicerConfigParser(conf_file)
+ parser.read(conf_file)
+ parser._defaults.setdefault(
+ 'here', os.path.dirname(os.path.abspath(conf_file)))
+ parser._defaults.setdefault(
+ '__file__', os.path.abspath(conf_file))
+
+ mgoblin_conf = dict(
+ [(section_name, dict(parser.items(section_name)))
+ for section_name in parser.sections()])
+
+ return mgoblin_conf
+
+
def setup_gettext(locale):
"""
Setup the gettext instance based on this locale
diff --git a/setup.py b/setup.py
index 097dd7f2..46da7276 100644
--- a/setup.py
+++ b/setup.py
@@ -41,6 +41,7 @@ setup(
'Babel',
'translitcodec',
'argparse',
+ 'webtest',
],
test_suite='nose.collector',
--
cgit v1.2.3
From e9279f21376feb5c43675c31b6f25e9fabac2ac6 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 4 Jun 2011 16:32:13 -0500
Subject: Added new render_template method which will make our lives nicer and
also will be useful for unit testing purposes :)
---
mediagoblin/util.py | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index fdb2c3f5..41f8a92a 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -78,6 +78,33 @@ def get_jinja_env(template_loader, locale):
return template_env
+# We'll store context information here when doing unit tests
+TEMPLATE_TEST_CONTEXT = {}
+
+
+def render_template(request, template, context):
+ """
+ Render a template with context.
+
+ Always inserts the request into the context, so you don't have to.
+ Also stores the context if we're doing unit tests. Helpful!
+ """
+ template = request.template_env.get_template(
+ template)
+ context['request'] = request
+ rendered = template.render(context)
+
+ if TESTS_ENABLED:
+ TEMPLATE_TEST_CONTEXT[template] = context
+
+ return rendered
+
+
+def clear_test_template_context():
+ global TEMPLATE_TEST_CONTEXT
+ TEMPLATE_TEST_CONTEXT = {}
+
+
def setup_user_in_request(request):
"""
Examine a request and tack on a request.user parameter if that's
--
cgit v1.2.3
From f99f61c65c7937910d7170f7f4a43c18e083a010 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 4 Jun 2011 16:44:22 -0500
Subject: Cache template environments and gettexts so we don't have to
reproduce them on every request.
---
mediagoblin/util.py | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index 41f8a92a..3649b6c3 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -25,6 +25,7 @@ import urllib
from math import ceil
import copy
+from babel.localedata import exists
import jinja2
import translitcodec
from paste.deploy.loadwsgi import NicerConfigParser
@@ -58,6 +59,9 @@ def get_jinja_loader(user_template_path=None):
return jinja2.PackageLoader('mediagoblin', 'templates')
+SETUP_JINJA_ENVS = {}
+
+
def get_jinja_env(template_loader, locale):
"""
Set up the Jinja environment,
@@ -67,6 +71,11 @@ def get_jinja_env(template_loader, locale):
"""
setup_gettext(locale)
+ # If we have a jinja environment set up with this locale, just
+ # return that one.
+ if SETUP_JINJA_ENVS.has_key(locale):
+ return SETUP_JINJA_ENVS[locale]
+
template_env = jinja2.Environment(
loader=template_loader, autoescape=True,
extensions=['jinja2.ext.i18n'])
@@ -75,6 +84,9 @@ def get_jinja_env(template_loader, locale):
mgoblin_globals.translations.gettext,
mgoblin_globals.translations.ngettext)
+ if exists(locale):
+ SETUP_JINJA_ENVS[locale] = template_env
+
return template_env
@@ -330,6 +342,8 @@ def read_config_file(conf_file):
return mgoblin_conf
+SETUP_GETTEXTS = {}
+
def setup_gettext(locale):
"""
Setup the gettext instance based on this locale
@@ -340,8 +354,13 @@ def setup_gettext(locale):
# TODO: fallback nicely on translations from pt_PT to pt if not
# available, etc.
- this_gettext = gettext.translation(
- 'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
+ if SETUP_GETTEXTS.has_key(locale):
+ this_gettext = SETUP_GETTEXTS[locale]
+ else:
+ this_gettext = gettext.translation(
+ 'mediagoblin', TRANSLATIONS_PATH, [locale], fallback=True)
+ if exists(locale):
+ SETUP_GETTEXTS[locale] = this_gettext
mgoblin_globals.setup_globals(
translations=this_gettext)
--
cgit v1.2.3
From b5d3aec615fd32439c9fc708d2266dc1cdfecc9d Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sat, 4 Jun 2011 17:36:36 -0500
Subject: Moving all views over to using util.render_template()!
---
mediagoblin/auth/views.py | 44 +++++++++++++++--------------------------
mediagoblin/edit/views.py | 9 ++++-----
mediagoblin/submit/views.py | 15 ++++++--------
mediagoblin/user_pages/views.py | 20 ++++++++-----------
mediagoblin/views.py | 10 +++++-----
5 files changed, 39 insertions(+), 59 deletions(-)
diff --git a/mediagoblin/auth/views.py b/mediagoblin/auth/views.py
index e4f1a7b1..2d24328d 100644
--- a/mediagoblin/auth/views.py
+++ b/mediagoblin/auth/views.py
@@ -18,6 +18,7 @@ import uuid
from webob import Response, exc
+from mediagoblin.util import render_template
from mediagoblin.db.util import ObjectId
from mediagoblin.auth import lib as auth_lib
from mediagoblin.auth import forms as auth_forms
@@ -58,20 +59,16 @@ def register(request):
location=request.urlgen("mediagoblin.auth.register_success"))
# render
- template = request.template_env.get_template(
- 'mediagoblin/auth/register.html')
return Response(
- template.render(
- {'request': request,
- 'register_form': register_form}))
+ render_template(
+ request, 'mediagoblin/auth/register.html',
+ {'register_form': register_form}))
def register_success(request):
- template = request.template_env.get_template(
- 'mediagoblin/auth/register_success.html')
return Response(
- template.render(
- {'request': request}))
+ render_template(
+ request, 'mediagoblin/auth/register_success.html', {}))
def login(request):
@@ -106,12 +103,10 @@ def login(request):
login_failed = True
# render
- template = request.template_env.get_template(
- 'mediagoblin/auth/login.html')
return Response(
- template.render(
- {'request': request,
- 'login_form': login_form,
+ render_template(
+ request, 'mediagoblin/auth/login.html',
+ {'login_form': login_form,
'next': request.GET.get('next') or request.POST.get('next'),
'login_failed': login_failed}))
@@ -146,12 +141,10 @@ def verify_email(request):
else:
verification_successful = False
- template = request.template_env.get_template(
- 'mediagoblin/auth/verify_email.html')
return Response(
- template.render(
- {'request': request,
- 'user': user,
+ render_template(
+ request, 'mediagoblin/auth/verify_email.html',
+ {'user': user,
'verification_successful': verification_successful}))
def verify_email_notice(request):
@@ -161,12 +154,9 @@ def verify_email_notice(request):
When the user tries to do some action that requires their account
to be verified beforehand, this view is called upon!
"""
-
- template = request.template_env.get_template(
- 'mediagoblin/auth/verification_needed.html')
return Response(
- template.render(
- {'request': request}))
+ render_template(
+ request, 'mediagoblin/auth/verification_needed.html', {}))
def resend_activation(request):
@@ -186,8 +176,6 @@ def resend_activation(request):
def resend_activation_success(request):
- template = request.template_env.get_template(
- 'mediagoblin/auth/resent_verification_email.html')
return Response(
- template.render(
- {'request': request}))
+ render_template(
+ request, 'mediagoblin/auth/resent_verification_email.html', {}))
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
index 0e0faa53..027a426c 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -17,6 +17,7 @@
from webob import Response, exc
+from mediagoblin.util import render_template
from mediagoblin.edit import forms
from mediagoblin.edit.lib import may_edit_media
from mediagoblin.decorators import require_active_login, get_user_media_entry
@@ -56,10 +57,8 @@ def edit_media(request, media):
user=media.uploader()['username'], media=media['slug']))
# render
- template = request.template_env.get_template(
- 'mediagoblin/edit/edit.html')
return Response(
- template.render(
- {'request': request,
- 'media': media,
+ render_template(
+ request, 'mediagoblin/edit/edit.html',
+ {'media': media,
'form': form}))
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 262f2b12..256f5be9 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -20,6 +20,7 @@ from cgi import FieldStorage
from webob import Response, exc
from werkzeug.utils import secure_filename
+from mediagoblin.util import render_template
from mediagoblin.decorators import require_active_login
from mediagoblin.submit import forms as submit_forms
from mediagoblin.process_media import process_media_initial
@@ -80,18 +81,14 @@ def submit_start(request):
location=request.urlgen("mediagoblin.submit.success"))
# render
- template = request.template_env.get_template(
- 'mediagoblin/submit/start.html')
return Response(
- template.render(
- {'request': request,
- 'submit_form': submit_form}))
+ render_template(
+ request, 'mediagoblin/submit/start.html',
+ {'submit_form': submit_form}))
def submit_success(request):
# render
- template = request.template_env.get_template(
- 'mediagoblin/submit/success.html')
return Response(
- template.render(
- {'request': request}))
+ render_template(
+ request, 'mediagoblin/submit/success.html', {}))
diff --git a/mediagoblin/user_pages/views.py b/mediagoblin/user_pages/views.py
index cc9c7b21..6ea3fe36 100644
--- a/mediagoblin/user_pages/views.py
+++ b/mediagoblin/user_pages/views.py
@@ -16,7 +16,7 @@
from webob import Response, exc
from mediagoblin.db.util import DESCENDING
-from mediagoblin.util import Pagination
+from mediagoblin.util import Pagination, render_template
from mediagoblin.decorators import uses_pagination, get_user_media_entry
@@ -42,13 +42,10 @@ def user_home(request, page):
if media_entries == None:
return exc.HTTPNotFound()
- template = request.template_env.get_template(
- 'mediagoblin/user_pages/user.html')
-
return Response(
- template.render(
- {'request': request,
- 'user': user,
+ render_template(
+ request, 'mediagoblin/user_pages/user.html',
+ {'user': user,
'media_entries': media_entries,
'pagination': pagination}))
@@ -56,12 +53,11 @@ def user_home(request, page):
@get_user_media_entry
def media_home(request, media):
"""'Homepage' of a MediaEntry()"""
- template = request.template_env.get_template(
- 'mediagoblin/user_pages/media.html')
return Response(
- template.render(
- {'request': request,
- 'media': media}))
+ render_template(
+ request, 'mediagoblin/user_pages/media.html',
+ {'media': media}))
+
ATOM_DEFAULT_NR_OF_UPDATED_ITEMS = 5
diff --git a/mediagoblin/views.py b/mediagoblin/views.py
index dd722c63..ee0b520a 100644
--- a/mediagoblin/views.py
+++ b/mediagoblin/views.py
@@ -15,15 +15,15 @@
# along with this program. If not, see .
from webob import Response
+
+from mediagoblin.util import render_template
from mediagoblin.db.util import DESCENDING
def root_view(request):
media_entries = request.db.MediaEntry.find(
{u'state': u'processed'}).sort('created', DESCENDING)
- template = request.template_env.get_template(
- 'mediagoblin/root.html')
return Response(
- template.render(
- {'request': request,
- 'media_entries': media_entries}))
+ render_template(
+ request, 'mediagoblin/root.html',
+ {'media_entries': media_entries}))
--
cgit v1.2.3
From 99619a625b20d4c5825eeb52753657b088db5381 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Sun, 5 Jun 2011 09:14:38 -0500
Subject: Firefox 3.X shows hidden fields for some reason, adding display:
none; to be rid of them for sure
---
mediagoblin/templates/mediagoblin/auth/login.html | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mediagoblin/templates/mediagoblin/auth/login.html b/mediagoblin/templates/mediagoblin/auth/login.html
index 22a57b70..c2e27c15 100644
--- a/mediagoblin/templates/mediagoblin/auth/login.html
+++ b/mediagoblin/templates/mediagoblin/auth/login.html
@@ -33,7 +33,8 @@
')
diff --git a/mediagoblin/util.py b/mediagoblin/util.py
index f29f8570..fc380f41 100644
--- a/mediagoblin/util.py
+++ b/mediagoblin/util.py
@@ -30,6 +30,7 @@ import jinja2
import translitcodec
from paste.deploy.loadwsgi import NicerConfigParser
from webob import Response, exc
+from lxml.html.clean import Cleaner
from mediagoblin import mg_globals
from mediagoblin.db.util import ObjectId
@@ -373,6 +374,32 @@ def read_config_file(conf_file):
return mgoblin_conf
+# A super strict version of the lxml.html cleaner class
+HTML_CLEANER = Cleaner(
+ scripts=True,
+ javascript=True,
+ comments=True,
+ style=True,
+ links=True,
+ page_structure=True,
+ processing_instructions=True,
+ embedded=True,
+ frames=True,
+ forms=True,
+ annoying_tags=True,
+ allow_tags=[
+ 'div', 'b', 'i', 'em', 'strong', 'p', 'ul', 'ol', 'li', 'a', 'br'],
+ remove_unknown_tags=False, # can't be used with allow_tags
+ safe_attrs_only=True,
+ add_nofollow=True, # for now
+ host_whitelist=(),
+ whitelist_tags=set([]))
+
+
+def clean_html(html):
+ return HTML_CLEANER.clean_html(html)
+
+
SETUP_GETTEXTS = {}
def setup_gettext(locale):
--
cgit v1.2.3
From 8bfa533f8b438e57a7950a8dcd02a275cbfa19df Mon Sep 17 00:00:00 2001
From: Elrond
Date: Tue, 14 Jun 2011 20:01:39 +0200
Subject: Drop WorkbenchManager.localized_file()
As Workbench has the localized_file() method, use this
everywhere and drop the wrapper method from
WorkbenchManager.
The processing code already did that.
---
mediagoblin/tests/test_workbench.py | 11 +++++------
mediagoblin/workbench.py | 3 ---
2 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/mediagoblin/tests/test_workbench.py b/mediagoblin/tests/test_workbench.py
index 2795cd63..db27dfc6 100644
--- a/mediagoblin/tests/test_workbench.py
+++ b/mediagoblin/tests/test_workbench.py
@@ -83,20 +83,19 @@ class TestWorkbench(object):
with this_storage.get_file(filepath, 'w') as our_file:
our_file.write('Our file')
- filename = self.workbench_manager.localized_file(
- this_workbench, this_storage, filepath)
+ filename = this_workbench.localized_file(this_storage, filepath)
assert filename == os.path.join(
this_workbench.dir, 'ourfile.txt')
# fake remote file storage, filename_if_copying set
- filename = self.workbench_manager.localized_file(
- this_workbench, this_storage, filepath, 'thisfile')
+ filename = this_workbench.localized_file(
+ this_storage, filepath, 'thisfile')
assert filename == os.path.join(
this_workbench.dir, 'thisfile.txt')
# fake remote file storage, filename_if_copying set,
# keep_extension_if_copying set to false
- filename = self.workbench_manager.localized_file(
- this_workbench, this_storage, filepath, 'thisfile.text', False)
+ filename = this_workbench.localized_file(
+ this_storage, filepath, 'thisfile.text', False)
assert filename == os.path.join(
this_workbench.dir, 'thisfile.text')
diff --git a/mediagoblin/workbench.py b/mediagoblin/workbench.py
index c88b686c..32229d2e 100644
--- a/mediagoblin/workbench.py
+++ b/mediagoblin/workbench.py
@@ -151,6 +151,3 @@ class WorkbenchManager(object):
"Can't destroy workbench outside the base workbench dir")
shutil.rmtree(workbench)
-
- def localized_file(self, workbench, *args, **kwargs):
- return workbench.localized_file(*args, **kwargs)
--
cgit v1.2.3
From b67a983a02363bd17a4e6a96e650e65aa2d4eb7a Mon Sep 17 00:00:00 2001
From: Elrond
Date: Tue, 14 Jun 2011 20:39:14 +0200
Subject: Move destroy_workbench to Workbench class
And add a lot of warnings, as the checks for "being part of
the main Manager" are all gone.
---
mediagoblin/process_media/__init__.py | 2 +-
mediagoblin/tests/test_workbench.py | 15 ++++--------
mediagoblin/workbench.py | 45 ++++++++++++++++-------------------
3 files changed, 25 insertions(+), 37 deletions(-)
diff --git a/mediagoblin/process_media/__init__.py b/mediagoblin/process_media/__init__.py
index bd067e39..f37bf080 100644
--- a/mediagoblin/process_media/__init__.py
+++ b/mediagoblin/process_media/__init__.py
@@ -75,4 +75,4 @@ def process_media_initial(media_id):
entry.save()
# clean up workbench
- mgg.workbench_manager.destroy_workbench(workbench)
+ workbench.destroy_self()
diff --git a/mediagoblin/tests/test_workbench.py b/mediagoblin/tests/test_workbench.py
index db27dfc6..953835a1 100644
--- a/mediagoblin/tests/test_workbench.py
+++ b/mediagoblin/tests/test_workbench.py
@@ -37,7 +37,7 @@ class TestWorkbench(object):
this_workbench = self.workbench_manager.create_workbench()
tmpname = this_workbench.joinpath('temp.txt')
assert tmpname == os.path.join(this_workbench.dir, 'temp.txt')
- self.workbench_manager.destroy_workbench(this_workbench)
+ this_workbench.destroy_self()
def test_destroy_workbench(self):
# kill a workbench
@@ -49,17 +49,10 @@ class TestWorkbench(object):
assert os.path.exists(tmpfile_name)
- self.workbench_manager.destroy_workbench(this_workbench)
+ wb_dir = this_workbench.dir
+ this_workbench.destroy_self()
assert not os.path.exists(tmpfile_name)
- assert not os.path.exists(this_workbench.dir)
-
- # make sure we can't kill other stuff though
- dont_kill_this = workbench.Workbench(tempfile.mkdtemp())
-
- assert_raises(
- workbench.WorkbenchOutsideScope,
- self.workbench_manager.destroy_workbench,
- dont_kill_this)
+ assert not os.path.exists(wb_dir)
def test_localized_file(self):
tmpdir, this_storage = get_tmp_filestorage()
diff --git a/mediagoblin/workbench.py b/mediagoblin/workbench.py
index 32229d2e..f83c4fa0 100644
--- a/mediagoblin/workbench.py
+++ b/mediagoblin/workbench.py
@@ -23,24 +23,21 @@ DEFAULT_WORKBENCH_DIR = os.path.join(
tempfile.gettempdir(), u'mgoblin_workbench')
-# Exception(s)
-# ------------
-
-class WorkbenchOutsideScope(Exception):
- """
- Raised when a workbench is outside a WorkbenchManager scope.
- """
- pass
-
-
# Actual workbench stuff
# ----------------------
class Workbench(object):
"""
Represent the directory for the workbench
+
+ WARNING: DO NOT create Workbench objects on your own,
+ let the WorkbenchManager do that for you!
"""
def __init__(self, dir):
+ """
+ WARNING: DO NOT create Workbench objects on your own,
+ let the WorkbenchManager do that for you!
+ """
self.dir = dir
def __unicode__(self):
@@ -117,6 +114,19 @@ class Workbench(object):
return full_dest_filename
+ def destroy_self(self):
+ """
+ Destroy this workbench! Deletes the directory and all its contents!
+
+ WARNING: Does no checks for a sane value in self.dir!
+ """
+ # just in case
+ workbench = os.path.abspath(self.dir)
+
+ shutil.rmtree(workbench)
+
+ del self.dir
+
class WorkbenchManager(object):
"""
@@ -136,18 +146,3 @@ class WorkbenchManager(object):
Create and return the path to a new workbench (directory).
"""
return Workbench(tempfile.mkdtemp(dir=self.base_workbench_dir))
-
- def destroy_workbench(self, workbench):
- """
- Destroy this workbench! Deletes the directory and all its contents!
-
- Makes sure the workbench actually belongs to this manager though.
- """
- # just in case
- workbench = os.path.abspath(workbench.dir)
-
- if not workbench.startswith(self.base_workbench_dir):
- raise WorkbenchOutsideScope(
- "Can't destroy workbench outside the base workbench dir")
-
- shutil.rmtree(workbench)
--
cgit v1.2.3
From 44e51d3464e719e596e1480b7af2957742a9085b Mon Sep 17 00:00:00 2001
From: Joar Wandborg
Date: Wed, 15 Jun 2011 23:07:54 +0200
Subject: Made changes according to http://bugs.foocorp.net/issues/363#note-5
---
mediagoblin/edit/views.py | 10 ++++++----
mediagoblin/submit/views.py | 10 ++++++----
2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/mediagoblin/edit/views.py b/mediagoblin/edit/views.py
index 2bc53a54..6c16a61e 100644
--- a/mediagoblin/edit/views.py
+++ b/mediagoblin/edit/views.py
@@ -17,11 +17,13 @@
from webob import exc
-from mediagoblin.util import render_to_response, redirect
+from mediagoblin.util import render_to_response, redirect, clean_html
from mediagoblin.edit import forms
from mediagoblin.edit.lib import may_edit_media
from mediagoblin.decorators import require_active_login, get_user_media_entry
+import markdown
+
@get_user_media_entry
@require_active_login
@@ -49,11 +51,11 @@ def edit_media(request, media):
media['title'] = request.POST['title']
media['description'] = request.POST.get('description')
- import markdown
md = markdown.Markdown(
safe_mode = 'escape')
- media['description_html'] = md.convert(
- media['description'])
+ media['description_html'] = clean_html(
+ md.convert(
+ media['description']))
media['slug'] = request.POST['slug']
media.save()
diff --git a/mediagoblin/submit/views.py b/mediagoblin/submit/views.py
index 21562e6f..437a5a51 100644
--- a/mediagoblin/submit/views.py
+++ b/mediagoblin/submit/views.py
@@ -19,11 +19,13 @@ from cgi import FieldStorage
from werkzeug.utils import secure_filename
-from mediagoblin.util import render_to_response, redirect
+from mediagoblin.util import render_to_response, redirect, clean_html
from mediagoblin.decorators import require_active_login
from mediagoblin.submit import forms as submit_forms, security
from mediagoblin.process_media import process_media_initial
+import markdown
+
@require_active_login
def submit_start(request):
@@ -49,11 +51,11 @@ def submit_start(request):
entry['title'] = request.POST['title'] or unicode(splitext(filename)[0])
entry['description'] = request.POST.get('description')
- import markdown
md = markdown.Markdown(
safe_mode = 'escape')
- entry['description_html'] = md.convert(
- entry['description'])
+ entry['description_html'] = clean_html(
+ md.convert(
+ entry['description']))
entry['media_type'] = u'image' # heh
entry['uploader'] = request.user['_id']
--
cgit v1.2.3
From f970e6e5df915081ca9c2951a4f8f0984aaec0e8 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Wed, 15 Jun 2011 21:14:00 -0500
Subject: Require ConfigObj
---
setup.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/setup.py b/setup.py
index 46da7276..37144b5b 100644
--- a/setup.py
+++ b/setup.py
@@ -42,6 +42,7 @@ setup(
'translitcodec',
'argparse',
'webtest',
+ 'ConfigObj',
],
test_suite='nose.collector',
--
cgit v1.2.3
From 0fcfff5a3a12fe7eeb0cabb862242776334879de Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Wed, 15 Jun 2011 21:17:55 -0500
Subject: Basic config "requirements" file.
Not used yet, but this will be used by ConfigObj to transform values,
set defaults, etc.
---
mediagoblin/config_spec.ini | 69 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)
create mode 100644 mediagoblin/config_spec.ini
diff --git a/mediagoblin/config_spec.ini b/mediagoblin/config_spec.ini
new file mode 100644
index 00000000..f91d1c1b
--- /dev/null
+++ b/mediagoblin/config_spec.ini
@@ -0,0 +1,69 @@
+[mediagoblin]
+#
+queuestore_base_dir = string(default="%(here)s/user_dev/media/queue")
+publicstore_base_dir = string(default="%(here)s/user_dev/media/public")
+
+# Where temporary files used in processing and etc are kept
+workbench_base_dir = string(default="%(here)s/user_dev/media/workbench")
+
+#
+publicstore_base_url = string(default="/mgoblin_media/")
+
+# Where mediagoblin-builtin static assets are kept
+direct_remote_path = string(default="/mgoblin_static/")
+
+# set to false to enable sending notices
+email_debug_mode = boolean(default=True)
+email_sender_address = string(default="notice@mediagoblin.example.org")
+
+local_templates = string(default="%(here)s/user_dev/templates/")
+
+# Whether or not celery is set up via an environment variable or
+# something else (and thus mediagoblin should not attempt to set it up
+# itself)
+celery_setup_elsewhere = boolean(default=False)
+
+[celery]
+# known booleans
+celery_result_persistent = boolean()
+celery_create_missing_queues = boolean()
+broker_use_ssl = boolean()
+broker_connection_retry = boolean()
+celery_always_eager = boolean()
+celery_eager_propagates_exceptions = boolean()
+celery_ignore_result = boolean()
+celery_track_started = boolean()
+celery_disable_rate_limits = boolean()
+celery_acks_late = boolean()
+celery_store_errors_even_if_ignored = boolean()
+celery_send_task_error_emails = boolean()
+celery_send_events = boolean()
+celery_send_task_sent_event = boolean()
+celeryd_log_color = boolean()
+celery_redirect_stdouts = boolean()
+
+# known ints
+celeryd_concurrency = integer()
+celeryd_prefetch_multiplier = integer()
+celery_amqp_task_result_expires = integer()
+celery_amqp_task_result_connection_max = integer()
+redis_port = integer()
+redis_db = integer()
+broker_port = integer()
+broker_connection_timeout = integer()
+celery_broker_connection_max_retries = integer()
+celery_task_result_expires = integer()
+celery_max_cached_results = integer()
+celery_default_rate_limit = integer()
+celeryd_max_tasks_per_child = integer()
+celeryd_task_time_limit = integer()
+celeryd_task_soft_time_limit = integer()
+mail_port = integer()
+celerybeat_max_loop_interval = integer()
+
+# known floats
+celeryd_eta_scheduler_precision = float()
+
+# known lists
+celery_routes = list()
+celery_imports = list()
\ No newline at end of file
--
cgit v1.2.3
From e2c6436e3e7c654a8d4196ac378debf185c74fa4 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 16 Jun 2011 08:21:51 -0500
Subject: Configuration file loading via ConfigObj.
Uses ConfigObj to open the config file. Also does validation via the
config spec, so defaults are provided, strings are interpolated, types
are converted.
---
mediagoblin/config.py | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 71 insertions(+)
create mode 100644 mediagoblin/config.py
diff --git a/mediagoblin/config.py b/mediagoblin/config.py
new file mode 100644
index 00000000..533dbe19
--- /dev/null
+++ b/mediagoblin/config.py
@@ -0,0 +1,71 @@
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import os
+import pkg_resources
+
+from configobj import ConfigObj
+from validate import Validator
+
+
+CONFIG_SPEC_PATH = pkg_resources.resource_filename(
+ 'mediagoblin', 'config_spec.ini')
+
+
+def _setup_defaults(config, config_path):
+ """
+ Setup DEFAULTS in a config object from an (absolute) config_path.
+ """
+ config.setdefault('DEFAULT', {})
+ config['DEFAULT']['here'] = os.path.dirname(config_path)
+ config['DEFAULT']['__file__'] = config_path
+
+
+def read_mediagoblin_config(config_path, config_spec=CONFIG_SPEC_PATH):
+ """
+ Read a config object from config_path.
+
+ Does automatic value transformation based on the config_spec.
+ Also provides %(__file__)s and %(here)s values of this file and
+ its directory respectively similar to paste deploy.
+
+ Args:
+ - config_path: path to the config file
+ - config_spec: config file that provides defaults and value types
+ for validation / conversion. Defaults to mediagoblin/config_spec.ini
+
+ Returns:
+ A read ConfigObj object.
+ """
+ config_path = os.path.abspath(config_path)
+
+ config_spec = ConfigObj(
+ CONFIG_SPEC_PATH,
+ encoding='UTF8', list_values=False, _inspec=True)
+
+ _setup_defaults(config_spec, config_path)
+
+ conf = ConfigObj(
+ config_path,
+ configspec=config_spec,
+ interpolation='ConfigParser')
+
+ _setup_defaults(conf, config_path)
+
+ conf.validate(Validator())
+
+ return conf
+
--
cgit v1.2.3
From 595944d46483112a9348df240cfb84a3ec2246f8 Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber
Date: Thu, 16 Jun 2011 08:33:10 -0500
Subject: Recommending --set-upstream when doing a git push to a feature
branch.
This is nice because it means git will tell you when your branch is
ahead/behind by several commits, assuming you keep working on it.
---
docs/git.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/git.rst b/docs/git.rst
index 8eb038b2..c3f7ccce 100644
--- a/docs/git.rst
+++ b/docs/git.rst
@@ -136,7 +136,7 @@ Slartibartfast does the following:
4. Slartibartfast pushes his changes to his clone (the remote is named
``origin``)::
- git push origin issue_42
+ git push origin issue_42 --set-upstream
5. Slartibartfast adds a comment to issue 42 with the url for his
repository and the name of the branch he put the code in. He also
--
cgit v1.2.3
From d49cf0e29c0165fcc2eddc5a324cf40b45fd1959 Mon Sep 17 00:00:00 2001
From: Caleb Forbes Davis V
Date: Fri, 3 Jun 2011 20:36:51 -0500
Subject: issue #330 - creates a user gallery template
---
.../templates/mediagoblin/user_pages/gallery.html | 40 ++++++++++++++++++++++
1 file changed, 40 insertions(+)
create mode 100644 mediagoblin/templates/mediagoblin/user_pages/gallery.html
diff --git a/mediagoblin/templates/mediagoblin/user_pages/gallery.html b/mediagoblin/templates/mediagoblin/user_pages/gallery.html
new file mode 100644
index 00000000..9e0c7d4a
--- /dev/null
+++ b/mediagoblin/templates/mediagoblin/user_pages/gallery.html
@@ -0,0 +1,40 @@
+{#
+# GNU MediaGoblin -- federated, autonomous media hosting
+# Copyright (C) 2011 Free Software Foundation, Inc
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#}
+{% extends "mediagoblin/base.html" %}
+
+{% block mediagoblin_head %}
+
+{% endblock mediagoblin_head %}
+
+{% block mediagoblin_content -%}
+ {% if user %}
+
'{{ user.username }}' gallery
+
+ {% include "mediagoblin/utils/object_gallery.html" %}
+
+ atom feed
+ {% else %}
+ {# This *should* not occur as the view makes sure we pass in a user. #}
+