Author: adc Date: Sun May 4 23:52:48 2014 New Revision: 1592432 URL: http://svn.apache.org/r1592432 Log: Handy WSGI script for ezmlm access
Added: labs/panopticon/bin/ezmlm.wsgi (contents, props changed) - copied, changed from r1592426, labs/panopticon/src/asf/utils/rest.py labs/panopticon/src/asf/utils/wsgi.py - copied, changed from r1592426, labs/panopticon/src/asf/utils/rest.py labs/panopticon/src/asf/wsgi/ labs/panopticon/src/asf/wsgi/__init__.py - copied, changed from r1592426, labs/panopticon/src/asf/utils/rest.py labs/panopticon/src/asf/wsgi/ezmlm.py Removed: labs/panopticon/src/asf/utils/rest.py Modified: labs/panopticon/setup.py Copied: labs/panopticon/bin/ezmlm.wsgi (from r1592426, labs/panopticon/src/asf/utils/rest.py) URL: http://svn.apache.org/viewvc/labs/panopticon/bin/ezmlm.wsgi?p2=labs/panopticon/bin/ezmlm.wsgi&p1=labs/panopticon/src/asf/utils/rest.py&r1=1592426&r2=1592432&rev=1592432&view=diff ============================================================================== --- labs/panopticon/src/asf/utils/rest.py (original) +++ labs/panopticon/bin/ezmlm.wsgi Sun May 4 23:52:48 2014 @@ -1,3 +1,4 @@ +# !/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file @@ -16,20 +17,14 @@ # specific language governing permissions and limitations # under the License. # -""" Flask decorators and utilities """ -from json import dumps - -from flask import current_app, request +CGI based WSGI API to mailing lists. +""" +import os -def json_result(f): - def wrapper(*args, **kwargs): - indent = None - if current_app.config['JSONIFY_PRETTYPRINT_REGULAR'] and not request.is_xhr: - indent = 2 - return current_app.response_class(dumps(f(*args, **kwargs), - indent=indent), - mimetype='application/json') +def application(environ, start_response): + os.environ['EZMLM_FLASK_CONFIG'] = environ['EZMLM_FLASK_CONFIG'] + from asf.wsgi.ezmlm import app - return wrapper \ No newline at end of file + return app.wsgi_app(environ, start_response) Propchange: labs/panopticon/bin/ezmlm.wsgi ------------------------------------------------------------------------------ svn:executable = * Modified: labs/panopticon/setup.py URL: http://svn.apache.org/viewvc/labs/panopticon/setup.py?rev=1592432&r1=1592431&r2=1592432&view=diff ============================================================================== --- labs/panopticon/setup.py (original) +++ labs/panopticon/setup.py Sun May 4 23:52:48 2014 @@ -102,7 +102,7 @@ setup( # don't ever depend on refcounting to close files anywhere else long_description=open('README.rst', encoding='utf-8').read(), - scripts=['bin/moderator'], + scripts=['bin/moderator', 'bin/ezmlm.wsgi'], namespace_packages=['asf'], package_dir={'': 'src'}, Copied: labs/panopticon/src/asf/utils/wsgi.py (from r1592426, labs/panopticon/src/asf/utils/rest.py) URL: http://svn.apache.org/viewvc/labs/panopticon/src/asf/utils/wsgi.py?p2=labs/panopticon/src/asf/utils/wsgi.py&p1=labs/panopticon/src/asf/utils/rest.py&r1=1592426&r2=1592432&rev=1592432&view=diff ============================================================================== --- labs/panopticon/src/asf/utils/rest.py (original) +++ labs/panopticon/src/asf/utils/wsgi.py Sun May 4 23:52:48 2014 @@ -18,12 +18,14 @@ # """ Flask decorators and utilities """ +from functools import wraps from json import dumps from flask import current_app, request def json_result(f): + @wraps(f) def wrapper(*args, **kwargs): indent = None if current_app.config['JSONIFY_PRETTYPRINT_REGULAR'] and not request.is_xhr: Copied: labs/panopticon/src/asf/wsgi/__init__.py (from r1592426, labs/panopticon/src/asf/utils/rest.py) URL: http://svn.apache.org/viewvc/labs/panopticon/src/asf/wsgi/__init__.py?p2=labs/panopticon/src/asf/wsgi/__init__.py&p1=labs/panopticon/src/asf/utils/rest.py&r1=1592426&r2=1592432&rev=1592432&view=diff ============================================================================== --- labs/panopticon/src/asf/utils/rest.py (original) +++ labs/panopticon/src/asf/wsgi/__init__.py Sun May 4 23:52:48 2014 @@ -7,7 +7,7 @@ # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an @@ -16,20 +16,6 @@ # specific language governing permissions and limitations # under the License. # -""" Flask decorators and utilities """ -from json import dumps - -from flask import current_app, request - - -def json_result(f): - def wrapper(*args, **kwargs): - indent = None - if current_app.config['JSONIFY_PRETTYPRINT_REGULAR'] and not request.is_xhr: - indent = 2 - return current_app.response_class(dumps(f(*args, **kwargs), - indent=indent), - mimetype='application/json') - - return wrapper \ No newline at end of file +Various WSGI based API scripts. +""" \ No newline at end of file Added: labs/panopticon/src/asf/wsgi/ezmlm.py URL: http://svn.apache.org/viewvc/labs/panopticon/src/asf/wsgi/ezmlm.py?rev=1592432&view=auto ============================================================================== --- labs/panopticon/src/asf/wsgi/ezmlm.py (added) +++ labs/panopticon/src/asf/wsgi/ezmlm.py Sun May 4 23:52:48 2014 @@ -0,0 +1,264 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +""" +CGI based WSGI API to mailing lists. +""" +from logging import getLogger +import os + +import flask + +from asf.utils.ezmlm import Ezmlm +from asf.utils.wsgi import json_result + + +log = getLogger(__name__) + +app = flask.Flask(__name__) +app.config.from_envvar('EZMLM_FLASK_CONFIG') + + +@app.route('/foo') +@json_result +def foo(): + return {'foo': 'bar'} + + +@app.route('/v1/public/lists') +@json_result +def public_lists(): + list_root_path = app.config['LIST_ROOT_PATH'] + + if not os.path.exists(list_root_path): + flask.abort(500) + + return ezmlm_list_groups(list_root_path) + + +@app.route('/v1/committer/lists') +@json_result +def committer_lists(): + list_path = app.config['LIST_ROOT_PATH'] + + if not os.path.exists(list_path): + flask.abort(500) + + return ezmlm_list_groups(list_path) + + +@app.route('/v1/asf/lists') +@json_result +def asf_lists(): + list_path = app.config['LIST_ROOT_PATH'] + + if not os.path.exists(list_path): + flask.abort(500) + + return ezmlm_list_groups(list_path) + + +# noinspection PyUnusedLocal +@app.route('/v1/public/lists/<mailing_list>/subscribers') +@json_result +def public_list_subscribers(mailing_list): + flask.abort(401) + + +# noinspection PyUnusedLocal +@app.route('/v1/committer/lists/<mailing_list>/subscribers') +@json_result +def committer_list_subscribers(mailing_list): + flask.abort(401) + + +@app.route('/v1/asf/lists/<mailing_list>/subscribers') +@json_result +def asf_list_subscribers(mailing_list): + list_path = path_from_root_and_list(app.config['LIST_ROOT_PATH'], mailing_list) + + if not os.path.exists(list_path): + flask.abort(500) + + return ezmlm_list_subscribers(list_path) + + +# noinspection PyUnusedLocal +@app.route('/v1/public/lists/<mailing_list>/moderators') +@json_result +def public_list_moderators(mailing_list): + flask.abort(401) + + +# noinspection PyUnusedLocal +@app.route('/v1/committer/lists/<mailing_list>/moderators') +@json_result +def committer_list_moderators(mailing_list): + flask.abort(401) + + +@app.route('/v1/asf/lists/<mailing_list>/moderators') +@json_result +def asf_list_moderators(mailing_list): + list_path = path_from_root_and_list(app.config['LIST_ROOT_PATH'], mailing_list) + + if not os.path.exists(list_path): + flask.abort(500) + + return ezmlm_list_moderators(list_path) + + +# noinspection PyUnusedLocal +@app.route('/v1/public/lists/<mailing_list>/subscribers/<subscriber>', methods=['PUT', 'DELETE']) +@json_result +def public_manage_subscribers(mailing_list, subscriber): + flask.abort(401) + + +# noinspection PyUnusedLocal +@app.route('/v1/committer/lists/<mailing_list>/subscribers/<subscriber>', methods=['PUT', 'DELETE']) +@json_result +def committer_manage_subscribers(mailing_list, subscriber): + flask.abort(401) + + +@app.route('/v1/asf/lists/<mailing_list>/subscribers/<subscriber>', methods=['PUT']) +@json_result +def asf_add_subscriber(mailing_list, subscriber): + list_path = path_from_root_and_list(app.config['LIST_ROOT_PATH'], mailing_list) + + if not os.path.exists(list_path): + flask.abort(500) + + return ezmlm_add_subscriber(list_path, subscriber) + + +@app.route('/v1/asf/lists/<mailing_list>/subscribers/<subscriber>', methods=['DELETE']) +@json_result +def asf_remove_subscriber(mailing_list, subscriber): + list_path = path_from_root_and_list(app.config['LIST_ROOT_PATH'], mailing_list) + + if not os.path.exists(list_path): + flask.abort(500) + + return ezmlm_remove_subscriber(list_path, subscriber) + + +# noinspection PyUnusedLocal +@app.route('/v1/public/lists/<mailing_list>/moderators/<moderator>', methods=['PUT', 'DELETE']) +@json_result +def public_manage_moderators(mailing_list, moderator): + flask.abort(401) + + +# noinspection PyUnusedLocal +@app.route('/v1/committer/lists/<mailing_list>/moderators/<moderator>', methods=['PUT', 'DELETE']) +@json_result +def committer_manage_moderators(mailing_list, moderator): + flask.abort(401) + + +@app.route('/v1/asf/lists/<mailing_list>/moderators/<moderator>', methods=['PUT']) +@json_result +def asf_add_moderator(mailing_list, moderator): + list_path = path_from_root_and_list(app.config['LIST_ROOT_PATH'], mailing_list) + + if not os.path.exists(list_path): + flask.abort(500) + + return ezmlm_add_moderator(list_path, moderator) + + +@app.route('/v1/asf/lists/<mailing_list>/moderators/<moderator>', methods=['DELETE']) +@json_result +def asf_remove_moderator(mailing_list, moderator): + list_path = path_from_root_and_list(app.config['LIST_ROOT_PATH'], mailing_list) + + if not os.path.exists(list_path): + flask.abort(500) + + return ezmlm_remove_moderator(list_path, moderator) + + +def path_from_root_and_list(list_root_path, mailing_list): + local, domain = mailing_list.split('@') + + list_groups = ezmlm_list_groups(list_root_path) + + if domain not in list_groups: + flask.abort(400) + + if local not in list_groups[domain]: + flask.abort(400) + + return os.path.join(list_root_path, domain, local) + + +def ezmlm_list_groups(list_root_path): + groups = {} + for domain in [o for o in os.listdir(list_root_path) if os.path.isdir(os.path.join(list_root_path, o)) and o.endswith('.apache.org')]: + groups[domain] = [] + domain_path = os.path.join(list_root_path, domain) + for mailing_list in os.listdir(domain_path): + groups[domain].append(mailing_list) + + return groups + + +def ezmlm_list_subscribers(list_path): + ezmlm = Ezmlm(list_path) + + subscribers = [] + for subscriber in sorted(ezmlm.subscribers): + subscribers.append(subscriber) + + return {'subscribers': subscribers} + + +def ezmlm_list_moderators(list_path): + ezmlm = Ezmlm(list_path) + + moderators = [] + for moderator in sorted(ezmlm.moderators): + moderators.append(moderator) + + return {'moderators': moderators} + + +def ezmlm_add_subscriber(list_path, subscriber): + ezmlm = Ezmlm(list_path) + + ezmlm.add_subscriber(subscriber) + + +def ezmlm_add_moderator(list_path, moderator): + ezmlm = Ezmlm(list_path) + + ezmlm.add_moderator(moderator) + + +def ezmlm_remove_subscriber(list_path, subscriber): + ezmlm = Ezmlm(list_path) + + ezmlm.remove_subscriber(subscriber) + + +def ezmlm_remove_moderator(list_path, moderator): + ezmlm = Ezmlm(list_path) + + ezmlm.remove_moderator(moderator) --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@labs.apache.org For additional commands, e-mail: commits-h...@labs.apache.org