<commit_before># 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 <http://www.gnu.org/licenses/>.

"""The RequestHandler for /upload URLs."""

import os
import tornado.web
import urlparse

import handlers.base as hbase
import handlers.common as hcommon
import handlers.response as hresponse
import models
import utils.upload

class UploadHandler(hbase.BaseHandler):
    """Handler the /upload URLs."""

    def __init__(self, application, request, **kwargs):
        super(UploadHandler, self).__init__(application, request, **kwargs)

    @property
    def collection(self):
        return self.db[models.UPLOAD_COLLECTION]

    @staticmethod
    def _token_validation_func():
        return hcommon.valid_token_upload

    @property
    def content_type(self):
        return "multipart/form-data"

    def execute_get(self, *args, **kwargs):
        """Execute the GET pre-operations.

        Checks that everything is OK to perform a GET.
        """
        response = None
        valid_token, _ = self.validate_req_token("GET")

        if valid_token:
            response = hresponse.HandlerResponse(501)
        else:
            response = hresponse.HandlerResponse(403)
            response.reason = hcommon.NOT_VALID_TOKEN

        return response

    def execute_delete(self, *args, **kwargs):
        """Perform DELETE pre-operations.

        Check that the DELETE request is OK.
        """
        # TODO: in the future we need to enable delete as well.
        response = None
        valid_token, _ = self.validate_req_token("DELETE")

        if valid_token:
            response = hresponse.HandlerResponse(501)
        else:
            response = hresponse.HandlerResponse(403)
            response.reason = hcommon.NOT_VALID_TOKEN

        return response

    def execute_post(self, *args, **kwargs):
        """Execute the POST pre-operations.

        Checks that everything is OK to perform a POST.
        """
        response = None
        valid_token, _ = self.validate_req_token("POST")

        if valid_token:
            valid_request = self._valid_post_request()

            if valid_request == 200:
                path = self.get_argument("path", None)
                if path is None:
                    try:
                        job = self.get_argument(models.JOB_KEY)
                        kernel = self.get_argument(models.KERNEL_KEY)
                        defconfig = self.get_argument(models.DEFCONFIG_KEY)
                        defconfig_full = self.get_argument(
                            models.DEFCONFIG_FULL, default=None)
                        arch = self.get_argument(models.ARCHITECTURE_KEY)
                        lab = self.get_argument(
                            models.LAB_NAME_KEY, default=None)

                        defconfig_path = "-".join(
                            [arch, (defconfig_full or defconfig)])

                        path = os.path.join(job, kernel, defconfig_path)
                        if lab is not None:
                            path = os.path.join(path, lab)
                    except tornado.web.MissingArgumentError, ex:
                        self.log.exception(ex)
                        response = hresponse.HandlerResponse(
                            ex.status_code)
                        response.reason = ex.log_message

                if path:
                    if not path.endswith("/"):
                        path += "/"
                    if path.startswith("/"):
                        path = path[1:]

                    if utils.upload.is_valid_dir_path(path):
                        ret_val, reason = \
                            utils.upload.check_or_create_upload_dir(path)
                        if ret_val == 200:
                            response = self._save_files(path)
                        else:
                            response = hresponse.HandlerResponse(ret_val)
                            response.reason = reason
                    else:
                        response = hresponse.HandlerResponse(400)
                        response.reason = "Provided path is not a directory"
            else:
                response = hresponse.HandlerResponse(valid_request)
                response.reason = (
                    "%s: %s" %
                    (
                        self._get_status_message(valid_request),
                        "Use %s as the content type" % self.content_type
                    )
                )
        else:
            response = hresponse.HandlerResponse(403)
            response.reason = hcommon.NOT_VALID_TOKEN

        return response

    def _put(self, *args, **kwargs):
        response = hresponse.HandlerResponse(201)

        if kwargs and kwargs.get("path", None):
            path = kwargs["path"]
            # Path points to a file, treat it like that.
            if path.endswith("/"):
                path = path[:-1]
            if path.startswith("/"):
                path = path[1:]

            filename = os.path.basename(path)
            dir_path = os.path.dirname(path)

            if utils.upload.is_valid_dir_path(dir_path):
                ret_val, error = \
                    utils.upload.check_or_create_upload_dir(dir_path)

                if ret_val == 200:
                    prev_file = utils.upload.file_exists(path)

                    ret_dict = utils.upload.create_or_update_file(
                        dir_path, filename, None, self.request.body)

                    if ret_dict["status"] == 200 or ret_dict["status"] == 201:
                        if prev_file:
                            response.status_code = 200
                            response.reason = (
                                "File '%s' replaced with new content" %
                                filename
                            )
                        else:
                            response.reason = "File '%s' saved" % filename
                            location = self._create_storage_url(path)
                            if location is not None:
                                response.headers = {"Location": location}
                    else:
                        response.status_code = ret_dict["status"]
                        response.reason = "Unable to save file"

                    response.result = [ret_dict]
                else:
                    response.status_code = ret_val
                    response.reason = error
            else:
                response.status_code = 500
                response.reason = (
                    "Cannot save file at the provided '%s' destination" % path)
        else:
            response.status_code = 400
            response.reason = "Missing destination path"

        return response

    def _create_storage_url(self, path):
        """Create the new storage location for the uploaded file.

        :param path: The path of the file.
        :type path: str
        :return The new storage URL.
        """
        storage_url = self.settings["storage_url"]
        new_storage_url = None

        if storage_url:
            split_url = urlparse.urlsplit(self.settings["storage_url"])
            new_storage_url = urlparse.urlunsplit(
                (
                    split_url.scheme, split_url.netloc, path, split_url.query,
                    split_url.fragment
                )
            )

        return new_storage_url

    def _save_files(self, path):
        """Parse the request and for each file, save it.

        :param path: The directory path where to save the files.
        :type str
        :return A `HandlerResponse` object.
        """
        response = hresponse.HandlerResponse()

        if self.request.files:
            response.result = [
                utils.upload.create_or_update_file(
                    path,
                    u_file[0]["filename"],
                    u_file[0]["content_type"],
                    u_file[0]["body"]
                )
                for u_file in self.request.files.itervalues()
            ]
        else:
            response.status_code = 400
            response.reason = "No files provided"

        return response
<commit_msg>Code cleanup.<commit_after># 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 <http://www.gnu.org/licenses/>.

"""The RequestHandler for /upload URLs."""

import os
import tornado.web
import urlparse

import handlers.base as hbase
import handlers.common as hcommon
import handlers.response as hresponse
import models
import utils.upload

class UploadHandler(hbase.BaseHandler):
    """Handler the /upload URLs."""

    def __init__(self, application, request, **kwargs):
        super(UploadHandler, self).__init__(application, request, **kwargs)

    @property
    def collection(self):
        return self.db[models.UPLOAD_COLLECTION]

    @staticmethod
    def _token_validation_func():
        return hcommon.valid_token_upload

    @property
    def content_type(self):
        return "multipart/form-data"

    def execute_get(self, *args, **kwargs):
        """Execute the GET pre-operations.

        Checks that everything is OK to perform a GET.
        """
        response = None
        valid_token, _ = self.validate_req_token("GET")

        if valid_token:
            response = hresponse.HandlerResponse(501)
        else:
            response = hresponse.HandlerResponse(403)
            response.reason = hcommon.NOT_VALID_TOKEN

        return response

    def execute_delete(self, *args, **kwargs):
        """Perform DELETE pre-operations.

        Check that the DELETE request is OK.
        """
        # TODO: in the future we need to enable delete as well.
        response = None
        valid_token, _ = self.validate_req_token("DELETE")

        if valid_token:
            response = hresponse.HandlerResponse(501)
        else:
            response = hresponse.HandlerResponse(403)
            response.reason = hcommon.NOT_VALID_TOKEN

        return response

    def execute_post(self, *args, **kwargs):
        """Execute the POST pre-operations.

        Checks that everything is OK to perform a POST.
        """
        response = None
        valid_token, _ = self.validate_req_token("POST")

        if valid_token:
            valid_request = self._valid_post_request()

            if valid_request == 200:
                path = self.get_argument("path", None)
                if path is None:
                    try:
                        job = self.get_argument(models.JOB_KEY)
                        kernel = self.get_argument(models.KERNEL_KEY)
                        defconfig = self.get_argument(models.DEFCONFIG_KEY)
                        defconfig_full = self.get_argument(
                            models.DEFCONFIG_FULL, default=None)
                        arch = self.get_argument(models.ARCHITECTURE_KEY)
                        lab = self.get_argument(
                            models.LAB_NAME_KEY, default=None)

                        defconfig_path = "-".join(
                            [arch, (defconfig_full or defconfig)])

                        path = os.path.join(job, kernel, defconfig_path)
                        if lab is not None:
                            path = os.path.join(path, lab)
                    except tornado.web.MissingArgumentError, ex:
                        self.log.exception(ex)
                        response = hresponse.HandlerResponse(
                            ex.status_code)
                        response.reason = ex.log_message

                if path:
                    if not path.endswith("/"):
                        path += "/"
                    if path.startswith("/"):
                        path = path[1:]

                    if utils.upload.is_valid_dir_path(path):
                        ret_val, reason = \
                            utils.upload.check_or_create_upload_dir(path)
                        if ret_val == 200:
                            response = self._save_files(path)
                        else:
                            response = hresponse.HandlerResponse(ret_val)
                            response.reason = reason
                    else:
                        response = hresponse.HandlerResponse(400)
                        response.reason = "Provided path is not a directory"
            else:
                response = hresponse.HandlerResponse(valid_request)
                response.reason = (
                    "%s: %s" %
                    (
                        self._get_status_message(valid_request),
                        "Use %s as the content type" % self.content_type
                    )
                )
        else:
            response = hresponse.HandlerResponse(403)
            response.reason = hcommon.NOT_VALID_TOKEN

        return response

    def _put(self, *args, **kwargs):
        response = hresponse.HandlerResponse(201)

        path = kwargs.get("path", None)
        if path:
            # Path points to a file, treat it like that.
            if path.endswith("/"):
                path = path[:-1]
            if path.startswith("/"):
                path = path[1:]

            filename = os.path.basename(path)
            dir_path = os.path.dirname(path)

            if utils.upload.is_valid_dir_path(dir_path):
                ret_val, error = \
                    utils.upload.check_or_create_upload_dir(dir_path)

                if ret_val == 200:
                    prev_file = utils.upload.file_exists(path)

                    ret_dict = utils.upload.create_or_update_file(
                        dir_path, filename, None, self.request.body)

                    if ret_dict["status"] == 200 or ret_dict["status"] == 201:
                        if prev_file:
                            response.status_code = 200
                            response.reason = (
                                "File '%s' replaced with new content" %
                                filename)
                        else:
                            response.reason = "File '%s' saved" % filename
                            location = self._create_storage_url(path)
                            if location is not None:
                                response.headers = {"Location": location}
                    else:
                        response.status_code = ret_dict["status"]
                        response.reason = "Unable to save file"

                    response.result = [ret_dict]
                else:
                    response.status_code = ret_val
                    response.reason = error
            else:
                response.status_code = 500
                response.reason = (
                    "Cannot save file at the provided '%s' destination" % path)
        else:
            response.status_code = 400
            response.reason = "Missing destination path"

        return response

    def _create_storage_url(self, path):
        """Create the new storage location for the uploaded file.

        :param path: The path of the file.
        :type path: str
        :return The new storage URL.
        """
        storage_url = self.settings["storage_url"]
        new_storage_url = None

        if storage_url:
            split_url = urlparse.urlsplit(storage_url)
            new_storage_url = urlparse.urlunsplit(
                (
                    split_url.scheme, split_url.netloc, path, split_url.query,
                    split_url.fragment
                )
            )

        return new_storage_url

    def _save_files(self, path):
        """Parse the request and for each file, save it.

        :param path: The directory path where to save the files.
        :type str
        :return A `HandlerResponse` object.
        """
        response = hresponse.HandlerResponse()

        if self.request.files:
            response.result = [
                utils.upload.create_or_update_file(
                    path,
                    u_file[0]["filename"],
                    u_file[0]["content_type"],
                    u_file[0]["body"]
                )
                for u_file in self.request.files.itervalues()
            ]
        else:
            response.status_code = 400
            response.reason = "No files provided"

        return response
<|endoftext|>


<commit_before>from .. import db
from geopy.geocoders import Nominatim

class ZIPCode(db.Model):
    __tablename__ = 'zip_codes'
    id = db.Column(db.Integer, primary_key=True)
    zip_code = db.Column(db.String(5), unique=True, index=True)
    users = db.relationship('User', backref='zip_code', lazy='dynamic')
    addresses = db.relationship('Address', backref='zip_code', lazy='dynamic')
    longitude = db.Column(db.Float)
    latitude = db.Column(db.Float)

    def __init__(self, zip_code):
        """
        If possible, the helper methods get_by_zip_code and create_zip_code
        should be used instead of explicitly using this constructor.
        """
        getcoords = Nominatim(country_bias='us')
        loc = getcoords.geocode(zip_code)
        if loc is None:
            raise ValueError('zip code \'%s\' is invalid' % self.zip_code)
        self.longitude = loc.longitude
        self.latitude = loc.latitude
        self.zip_code = zip_code

    @staticmethod
    def get_by_zip_code(zip_code):
        """Helper for searching by 5 digit zip codes."""
        result = ZIPCode.query.filter_by(zip_code=zip_code).first()
        return result

    @staticmethod
    def create_zip_code(zip_code):
        """
        Helper to create a ZIPCode entry. Returns the newly created ZIPCode
        or the existing entry if zip_code is already in the table.
        """
        result = ZIPCode.get_by_zip_code(zip_code)
        if result is None:
            result = ZIPCode(zip_code=zip_code)
            db.session.add(result)
            db.session.commit()
        return result

    @staticmethod
    def generate_fake():
        """Generate count fake ZIPCodes for testing."""
        zippy = ['19104', '01810', '02420', '75205', '94305', '47906', '60521']

        for zip in zippy:
            ZIPCode.create_zip_code(zip)

    def __repr__(self):
        return '<ZIPCode \'%s\'>' % self.zip_code

class Address(db.Model):
    __tablename__ = 'addresses'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text)         # ABC MOVERS
    street_address = db.Column(db.Text)  # 1500 E MAIN AVE STE 201
    city = db.Column(db.Text)
    state = db.Column(db.String(2))
    zip_code_id = db.Column(db.Integer, db.ForeignKey('zip_codes.id'))
    resources = db.relationship('Resource', backref='address', lazy='dynamic')

    def __repr__(self):
        return '<Address \'%s\'>' % self.name
<commit_msg>almost nothing has changed since the last commit<commit_after>from .. import db
from geopy.geocoders import Nominatim

class ZIPCode(db.Model):
    __tablename__ = 'zip_codes'
    id = db.Column(db.Integer, primary_key=True)
    zip_code = db.Column(db.String(5), unique=True, index=True)
    users = db.relationship('User', backref='zip_code', lazy='dynamic')
    addresses = db.relationship('Address', backref='zip_code', lazy='dynamic')
    longitude = db.Column(db.Float)
    latitude = db.Column(db.Float)

    def __init__(self, zip_code):
        """
        If possible, the helper methods get_by_zip_code and create_zip_code
        should be used instead of explicitly using this constructor.
        """
        getcoords = Nominatim(country_bias='us')
        loc = getcoords.geocode(zip_code)
        if loc is None:
            raise ValueError('zip code \'%s\' is invalid' % zip_code)
        self.longitude = loc.longitude
        self.latitude = loc.latitude
        self.zip_code = zip_code

    @staticmethod
    def get_by_zip_code(zip_code):
        """Helper for searching by 5 digit zip codes."""
        result = ZIPCode.query.filter_by(zip_code=zip_code).first()
        return result

    @staticmethod
    def create_zip_code(zip_code):
        """
        Helper to create a ZIPCode entry. Returns the newly created ZIPCode
        or the existing entry if zip_code is already in the table.
        """
        result = ZIPCode.get_by_zip_code(zip_code)
        if result is None:
            result = ZIPCode(zip_code=zip_code)
            db.session.add(result)
            db.session.commit()
        return result

    @staticmethod
    def generate_fake():
        """Generate count fake ZIPCodes for testing."""
        zippy = ['19104', '01810', '02420', '75205', '94305', '47906', '60521']

        for zip in zippy:
            ZIPCode.create_zip_code(zip)

    def __repr__(self):
        return '<ZIPCode \'%s\'>' % self.zip_code

class Address(db.Model):
    __tablename__ = 'addresses'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text)         # ABC MOVERS
    street_address = db.Column(db.Text)  # 1500 E MAIN AVE STE 201
    city = db.Column(db.Text)
    state = db.Column(db.String(2))
    zip_code_id = db.Column(db.Integer, db.ForeignKey('zip_codes.id'))
    resources = db.relationship('Resource', backref='address', lazy='dynamic')

    def __repr__(self):
        return '<Address \'%s\'>' % self.name
<|endoftext|>


<commit_before>#!/usr/bin/python2.5
#
# Copyright 2008 the Melange authors.
#
# Licensed 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.

"""Module containing enhanced db.Model classes.

The classes in this module are intended to serve as base classes for all
Melange Datastore Models.
"""

__authors__ = [
  '"Todd Larsen" <tlarsen@google.com>',
  '"Lennard de Rijk" <ljvderijk@gmail.com>',
]

from google.appengine.ext import db

from soc.views.helper import forms as forms_helper

class ModelWithFieldAttributes(db.Model):
  """A db.Model extension that provides access to Model properties attributes.

  Due to the way the Property class in Google App Engine implements __get__()
  and __set__(), it is not possible to access attributes of Model properties,
  such as verbose_name, from within a Django template.  This class works
  around that limitation by creating an inner Form class per Model class,
  since an unbound Form object contains (most of?) the property attributes
  attached to each corresponding Form field.

  Some are attributes are renamed during the conversion from a Model Property
  to a Form field; for example, verbose_name becomes label.  This is tolerable
  because any actual Form code refers to these new names, so they are should
  be familiar to view creators.
  """

  _fields_cache = None
  DICT_TYPES = (db.StringProperty, db.IntegerProperty)

  def toDict(self, field_names=None):
    """Returns a dict with all specified values of this entity.

    Args:
      field_names: the fields that should be included, defaults to
        all fields that are of a type that is in DICT_TYPES.
    """

    result = {}

    if not field_names:
      props = self.properties().iteritems()
      field_names = [k for k, v in props if isinstance(v, self.DICT_TYPES)]

    for key in field_names:
      # Skip everything that is not valid
      if not hasattr(self, key):
        continue

      value = getattr(self, key)

      if callable(value):
        value = value()

      result[key] = value

    return result

  @classmethod
  def fields(cls):
    """Called by the Django template engine during template instantiation.

    Since the attribute names use the Form fields naming instead of the
    Property attribute naming, accessing, for example:
      {{ entity.property.verbose_name }}
    is accomplished using:
      {{ entity.fields.property.label }}

    Args:
      cls: Model class, so that each Model class can create its own
        unbound Form the first time fields() is called by the Django
        template engine.

    Returns:
      A (created-on-first-use) unbound Form object that can be used to
      access Property attributes that are not accessible from the
      Property itself via the Model entity.
    """
    if not cls._fields_cache or (cls != cls._fields_cache.__class__.Meta.model):
      class FieldsProxy(forms_helper.BaseForm):
        """Form used as a proxy to access User model properties attributes.
        """

        class Meta:
          """Inner Meta class that pairs the User Model with this "form".
          """
          #: db.Model subclass for which to access model properties attributes
          model = cls

      cls._fields_cache = FieldsProxy()
    return cls._fields_cache
<commit_msg>Convert datetime fields to strs in toDict<commit_after>#!/usr/bin/python2.5
#
# Copyright 2008 the Melange authors.
#
# Licensed 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.

"""Module containing enhanced db.Model classes.

The classes in this module are intended to serve as base classes for all
Melange Datastore Models.
"""

__authors__ = [
  '"Todd Larsen" <tlarsen@google.com>',
  '"Lennard de Rijk" <ljvderijk@gmail.com>',
]

from google.appengine.ext import db

from soc.views.helper import forms as forms_helper

import datetime

class ModelWithFieldAttributes(db.Model):
  """A db.Model extension that provides access to Model properties attributes.

  Due to the way the Property class in Google App Engine implements __get__()
  and __set__(), it is not possible to access attributes of Model properties,
  such as verbose_name, from within a Django template.  This class works
  around that limitation by creating an inner Form class per Model class,
  since an unbound Form object contains (most of?) the property attributes
  attached to each corresponding Form field.

  Some are attributes are renamed during the conversion from a Model Property
  to a Form field; for example, verbose_name becomes label.  This is tolerable
  because any actual Form code refers to these new names, so they are should
  be familiar to view creators.
  """

  _fields_cache = None
  DICT_TYPES = (db.StringProperty, db.IntegerProperty)
  STR_TYPES = (datetime.datetime)

  def toDict(self, field_names=None):
    """Returns a dict with all specified values of this entity.

    Args:
      field_names: the fields that should be included, defaults to
        all fields that are of a type that is in DICT_TYPES.
    """

    result = {}

    if not field_names:
      props = self.properties().iteritems()
      field_names = [k for k, v in props if isinstance(v, self.DICT_TYPES)]

    for key in field_names:
      # Skip everything that is not valid
      if not hasattr(self, key):
        continue

      value = getattr(self, key)

      if callable(value):
        value = value()

      if isinstance(value, self.STR_TYPES):
        value = str(value)

      result[key] = value

    return result

  @classmethod
  def fields(cls):
    """Called by the Django template engine during template instantiation.

    Since the attribute names use the Form fields naming instead of the
    Property attribute naming, accessing, for example:
      {{ entity.property.verbose_name }}
    is accomplished using:
      {{ entity.fields.property.label }}

    Args:
      cls: Model class, so that each Model class can create its own
        unbound Form the first time fields() is called by the Django
        template engine.

    Returns:
      A (created-on-first-use) unbound Form object that can be used to
      access Property attributes that are not accessible from the
      Property itself via the Model entity.
    """
    if not cls._fields_cache or (cls != cls._fields_cache.__class__.Meta.model):
      class FieldsProxy(forms_helper.BaseForm):
        """Form used as a proxy to access User model properties attributes.
        """

        class Meta:
          """Inner Meta class that pairs the User Model with this "form".
          """
          #: db.Model subclass for which to access model properties attributes
          model = cls

      cls._fields_cache = FieldsProxy()
    return cls._fields_cache
<|endoftext|>


<commit_before>#!/usr/bin/python2.5
#
# Copyright 2008 the Melange authors.
#
# Licensed 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.

"""This module contains the User Model."""

__authors__ = [
  '"Todd Larsen" <tlarsen@google.com>',
  '"Sverre Rabbelier" <sverre@rabbelier.nl>',
  '"Pawel Solyga" <pawel.solyga@gmail.com>',
]

from google.appengine.api import users
from google.appengine.ext import db

from django.utils.translation import ugettext

import soc.models.linkable

class User(soc.models.linkable.Linkable):
  """A user and associated login credentials, the fundamental identity entity.

  User is a separate Model class from Person because the same login
  ID may be used to, for example, serve as Contributor in one Program
  and a Reviewer in another.

  Also, this allows a Person to, in the future, re-associate that
  Person entity with a different Google Account if necessary.

  A User entity participates in the following relationships implemented
  as a db.ReferenceProperty elsewhere in another db.Model:

   persons)  a 1:many relationship of Person entities identified by the
     User.  This relation is implemented as the 'persons' back-reference
     Query of the Person model 'user' reference.

   documents)  a 1:many relationship of Document entities identified by the
     User.  This relation is implemented as the 'user' back-reference
     Query of the Document model 'user' reference.

   groups)  a 1:many relationship of Group entities "founded" by the User.
     This relation is implemented as the 'groups' back-reference Query of
     the Group model 'founder' reference.

   responses)  a 1:many relationship of Reponse entities submitted by the
     User.  This relation is implemented as the 'responses' back-reference
     Query of the Response model 'respondent' reference.
  """

  URL_NAME = 'user'

  #: A Google Account, which also provides a "private" email address.
  #: This email address is only used in an automated fashion by
  #: Melange web applications and is not made visible to other users
  #: of any Melange application.
  account = db.UserProperty(required=True,
      verbose_name=ugettext('User account'))
  account.help_text = ugettext(
      'A valid Google Account.')

  #: Google Account unique user id
  user_id = db.StringProperty(required=False)

  #: A list (possibly empty) of former Google Accounts associated with
  #: this User.
  former_accounts = db.ListProperty(users.User)

  #: Required field storing publicly-displayed name.  Can be a real name
  #: (though this is not recommended), or a nick name or some other public
  #: alias.  Public names can be any valid UTF-8 text.
  name = db.StringProperty(required=True,
      verbose_name=ugettext('Public name'))
  name.help_text = ugettext(
      'Human-readable name (UTF-8) that will be displayed publicly on the'
      ' site.')

  #: field storing whether User is a Developer with site-wide access.
  is_developer = db.BooleanProperty(default=False,
      verbose_name=ugettext('Is Developer'))
  is_developer.help_text = ugettext(
      'Field used to indicate user with site-wide Developer access.')

  #: field storing wheter the User has agreed to the site-wide Terms of Service.
  #: (Not a required field because the Terms of Service might not be present
  #: when the first User profile is created when bootstrapping the site.)
  agreed_to_tos = db.BooleanProperty(required=False, default=False,
      verbose_name=ugettext('I Agree to the Terms of Service'))
  agreed_to_tos.help_text = ugettext(
      'Indicates whether the user agreed to the site-wide Terms of Service.')

  #: field storing when the User has agreed to the site-wide Terms of Service.
  #: (Not a required field because the Terms of Service might not be present
  #: when the first User profile is created when bootstrapping the site.)
  agreed_to_tos_on = db.DateTimeProperty(required=False, default=None,
      verbose_name=ugettext('Has agreed to the Terms of Service on'))
  agreed_to_tos_on.help_text = ugettext(
      'Indicates when the user agreed to the site-wide Terms of Service.')

  #: field storing the status of this User.
  #: valid: Is just that, it's a valid User.
  #: invalid: This means that this User has been excluded
  #:          from using the website.
  status = db.StringProperty(required=True, default='valid',
      choices=['valid', 'invalid'],)
  status.help_text = ugettext(
      'Indicates the status of the User. Invalid means that this account '
      'has been excluded from using the website.')
<commit_msg>Whitespace fix in User model.<commit_after>#!/usr/bin/python2.5
#
# Copyright 2008 the Melange authors.
#
# Licensed 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.

"""This module contains the User Model."""

__authors__ = [
  '"Todd Larsen" <tlarsen@google.com>',
  '"Sverre Rabbelier" <sverre@rabbelier.nl>',
  '"Pawel Solyga" <pawel.solyga@gmail.com>',
]

from google.appengine.api import users
from google.appengine.ext import db

from django.utils.translation import ugettext

import soc.models.linkable

class User(soc.models.linkable.Linkable):
  """A user and associated login credentials, the fundamental identity entity.

  User is a separate Model class from Person because the same login
  ID may be used to, for example, serve as Contributor in one Program
  and a Reviewer in another.

  Also, this allows a Person to, in the future, re-associate that
  Person entity with a different Google Account if necessary.

  A User entity participates in the following relationships implemented
  as a db.ReferenceProperty elsewhere in another db.Model:

   persons)  a 1:many relationship of Person entities identified by the
     User.  This relation is implemented as the 'persons' back-reference
     Query of the Person model 'user' reference.

   documents)  a 1:many relationship of Document entities identified by the
     User.  This relation is implemented as the 'user' back-reference
     Query of the Document model 'user' reference.

   groups)  a 1:many relationship of Group entities "founded" by the User.
     This relation is implemented as the 'groups' back-reference Query of
     the Group model 'founder' reference.

   responses)  a 1:many relationship of Reponse entities submitted by the
     User.  This relation is implemented as the 'responses' back-reference
     Query of the Response model 'respondent' reference.
  """

  URL_NAME = 'user'

  #: A Google Account, which also provides a "private" email address.
  #: This email address is only used in an automated fashion by
  #: Melange web applications and is not made visible to other users
  #: of any Melange application.
  account = db.UserProperty(required=True,
      verbose_name=ugettext('User account'))
  account.help_text = ugettext(
      'A valid Google Account.')

  #: Google Account unique user id
  user_id = db.StringProperty(required=False)

  #: A list (possibly empty) of former Google Accounts associated with
  #: this User.
  former_accounts = db.ListProperty(users.User)

  #: Required field storing publicly-displayed name.  Can be a real name
  #: (though this is not recommended), or a nick name or some other public
  #: alias.  Public names can be any valid UTF-8 text.
  name = db.StringProperty(required=True,
      verbose_name=ugettext('Public name'))
  name.help_text = ugettext(
      'Human-readable name (UTF-8) that will be displayed publicly on the'
      ' site.')

  #: field storing whether User is a Developer with site-wide access.
  is_developer = db.BooleanProperty(default=False,
      verbose_name=ugettext('Is Developer'))
  is_developer.help_text = ugettext(
      'Field used to indicate user with site-wide Developer access.')

  #: field storing wheter the User has agreed to the site-wide Terms of Service.
  #: (Not a required field because the Terms of Service might not be present
  #: when the first User profile is created when bootstrapping the site.)
  agreed_to_tos = db.BooleanProperty(required=False, default=False,
      verbose_name=ugettext('I Agree to the Terms of Service'))
  agreed_to_tos.help_text = ugettext(
      'Indicates whether the user agreed to the site-wide Terms of Service.')

  #: field storing when the User has agreed to the site-wide Terms of Service.
  #: (Not a required field because the Terms of Service might not be present
  #: when the first User profile is created when bootstrapping the site.)
  agreed_to_tos_on = db.DateTimeProperty(required=False, default=None,
      verbose_name=ugettext('Has agreed to the Terms of Service on'))
  agreed_to_tos_on.help_text = ugettext(
      'Indicates when the user agreed to the site-wide Terms of Service.')

  #: field storing the status of this User.
  #: valid: Is just that, it's a valid User.
  #: invalid: This means that this User has been excluded
  #:          from using the website.
  status = db.StringProperty(required=True, default='valid',
      choices=['valid', 'invalid'],)
  status.help_text = ugettext(
      'Indicates the status of the User. Invalid means that this account '
      'has been excluded from using the website.')
<|endoftext|>


<commit_before>#-*- coding:utf -*-

import functools
import inspect
import re
import logging
import json
logging.basicConfig(level=logging.INFO)
from   tools.log import Log
from   tools.session import SessionManager
from   tools.config import Config
import os
try:
	import asyncio
except ImportError:
	logging.error("Can't Found Module asyncio")

try:
	import aiohttp
	import aiohttp.web
	import aiohttp.errors
	from aiohttp import web
except ImportError:
	logging.error("Can't Found Module aiohttp")

class AppContainer(dict):
	def __init__(self,app,**kw):
		self._post=app['post']
		self._get=app['get']
		self._app=app
		self._cookie=app['cookie']
		self._app['set_cookie']=[]
		self._app['del_cookie']=[]
		self._app['response']=''
		self._app['redirect']=''
		self._app['status']=''
		self._config=Config
		super(AppContainer,self).__init__(**kw)
	def get_argument(self,name,default=None):
		if name not  in self._post and name not in self._get:
			return default
		if name in self._post:
			return self._post[name]
		if name in self._get:
			return self._get[name]
	def get_all_cookies(self):
		return self._cookie
	def get_cookie(self,cookie_name,default=None):
		if cookie_name in self._cookie:
			return self._cookie[cookie_name]
		return default
	def set_cookie(self,cookie_name,cookie_value,expire=None,*,domain=None,max_age=None,httponly=False,path='/'):
		self._app['set_cookie'].append({'cookie_name':cookie_name,'cookie_value':cookie_value,
'expire':expire,'domain':domain,'path':path,'max-age':max_age,'httponly':httponly})
	def clear_cookie(self,name,*,path='/',domain=None):
		self._app['del_cookie'].append({'cookie_name':name,'path':path,'domain':domain})

	def clear_all_cookies(self):
		if self._cookie:
			for ck in self._cookie:
				self.clear_cookie(ck)
	def render(self,content,**kw):
		if re.match('^[\w]+.html$',content):
			self._app['response']={'__template__':content,'parameter':kw}
		else:
			self._app['response']=content
	@property
	def session(self):
		if not hasattr(self,'_session_instance'):
			session_id=self.get_cookie('ssnid')
			if not session_id:
				session_id=self.get_argument("ssnid")
			if not session_id:
				self._session_instance=SessionManager(driver=self._config.session.driver_name,config=self._config.session.all)
			else:
				self._session_instance=SessionManager(session_id,driver=self._config.session.driver_name,config=self._config.session.all)
		return self._session_instance
	def session_end(self,expire=None):
		if hasattr(self,'_session_instance'):
			self.set_cookie('ssnid',self._session_instance.session_id)
			self._session_instance.save(expire)
	def session_destroy(self,session_id=None):
		if session_id:
			if not hasattr(self,'_session_instance'):
				self._session_instance=SessionManager(driver=self._config.session.driver_name,config=self._config.session.all)
			self._session_instance.delete(session_id)
		else:
			session_id=self.get_cookie("ssnid")
			if  session_id:
				self.clear_cookie('ssnid')
				if not hasattr(self,'_session_instance'):
					self._session_instance=SessionManager(driver=self._config.session.driver_name,config=self._config.session.all)
				self._session_instance.delete(session_id)
	def auth(self,auth=False):
		if auth:
			user_id=self.session[self._config.authentication.auth_id]
			if not user_id:
				self.redirect(self._config.authentication.login_url)
	def redirect(self,url):
		self._app['redirect']=url
	def set_status(self,code,*,message=None):
		assert isinstance(code,int)
		if message:
			self._app['status']={'code':code,'message':message}
		else:
			error_template_name='errors/'+str(code)+'.html'
			self._app['status']={'code':code,'message':self._app['__templating__'].get_template(error_template_name).render()}
class BaseHandler(object):
	r'''
			basic handler process url paramter

	'''
	def __init__(self,app,handlerfn):
		self._app=app
		self._handler=handlerfn
	def _param_generator(self,l):
		def _generator():
			for k in l:
				yield k
		return _generator
	@asyncio.coroutine
	def __call__(self,request):
		post=yield from request.post()
		get=request.GET
		cookie=request.cookies
		self._app['cookie']=request.cookies if request.cookies else {}
		self._app['get']=request.GET if request.GET else {}
		self._app['post']=post if post else {}
		container=AppContainer(app=self._app)
		container.auth(self._handler.__auth__)
		args=self._handler.__args__
		if len(args)==1:
			response=yield from self._handler(container)
		elif len(args)>1:
			param={}
			for k in args[1:]:
				if k not in request.match_info :
					raise NameError("Can't Found '%s'"%k)
				param[k]=request.match_info[k]
			param[self._handler.__args__[0]]=container
			response=yield from self._handler(**param)
		else:
			response=None
		return response

class Middleware(object):
	def http_error_handler(app,handler):
		@asyncio.coroutine
		def _handler(request):
			res=yield from handler(request)
			if app.get('status'):
				res=web.Response(status=app.get('status').get('code'),body=app.get('status').get('message').encode('utf-8'))
				return res
			return res
		return _handler
	def response(app,handler):
		def check_set_cookie(res):
			if len(app['set_cookie'])>0:
				for k in app['set_cookie']:
					res.set_cookie(k['cookie_name'],k['cookie_value'],path=k['path'],expires=k['expire'],domain=k['domain'],httponly=k['httponly'])
			return res
		def check_del_cookie(res):
			if len(app['del_cookie'])>0:
				for k in app['del_cookie']:
					res.del_cookie(k['cookie_name'],path=k['path'],domain=k['domain'])
			return res
		@asyncio.coroutine
		def _response(request):
			res=yield from handler(request)
			res=res if res else app.get('response')
			if app.get('redirect'):
				redirect_url=app.get('redirect')
				app['redirect']=''
				res= aiohttp.web.HTTPFound(redirect_url)
				check_set_cookie(res)
				check_del_cookie(res)
				return res
			if isinstance(res,web.StreamResponse):
				res=res
			elif isinstance(res,bytes):
				res=web.Response(body=res)
				res.content_type='application/octet-stream'
			elif isinstance(res,str):
				res=web.Response(body=res.encode("utf-8"))
				res.content_type='text/html;charset=utf-8'
			elif isinstance(res,dict):
				template=res.get('__template__')
				if template is None:
					res=web.Response(body=json.dumps(res,ensure_ascii=False,default=lambda x:x.__dict__).encode("utf-8"))
					res.content_type='application/json;charset=utf-8'
				else:
					res=web.Response(body=app['__templating__'].get_template(template).render(**res['parameter']).encode("utf-8"))
					res.content_type='text/html;charset=utf-8'
			else:
				res=res
			res=check_set_cookie(res)
			res=check_del_cookie(res)
			return res
		return _response
	def log(app,handler):
		@asyncio.coroutine
		def _log(request):
			Log.info("%s:%s===>%s"%(request.host,request.method,request))
			return (yield from handler(request))
		return _log
	@classmethod
	def allmiddlewares(cls):
		middlewares=list()
		for k,v in cls.__dict__.items():
			if k.startswith('__') and k.endswith('__') or k=='allmiddlewares':
				continue
			if not asyncio.iscoroutinefunction(v):
				v=asyncio.coroutine(v)
			middlewares.append(v)
		return middlewares

class Route(object):
	r'''
		Route class is responsible for routes adding and routes registering to  aiohttp
	'''
	_none_variable_routes=list()
	_incomplete_variable_routes=list()
	_complete_variable_routes=list()
	def __init__(self):
		pass
	@classmethod
	def add_routes(cls,wrapper):
		if wrapper.__url__.count('{')!=0:
			if wrapper.__url__.endswith('/'):
				wrapper.__url__=wrapper.__url__[:wrapper.__url__.rindex('/')]
			if wrapper.__url__.count('{')<wrapper.__url__.count('/'):
				Route._incomplete_variable_routes.append(wrapper)
			else:
				Route._complete_variable_routes.append(wrapper)
		else:
			Route._none_variable_routes.append(wrapper)
	@classmethod
	def get(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='GET'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			cls.add_routes(wrapper)
			return wrapper
		return decorator
	@classmethod
	def post(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='POST'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			cls.add_routes(wrapper)
			return wrapper
		return decorator
	@classmethod
	def put(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='PUT'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			cls.add_routes(wrapper)
			return wrapper
		return decorator
	@classmethod
	def delete(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='DELETE'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			cls.add_routes(wrapper)
			return wrapper
		return decorator
	@classmethod
	def sort_variable_routes(cls,routes):
		route_length=len(routes)
		i=0
		while i<route_length:
			j=i
			while j>0 and routes[j].__url__.count('{')<routes[j-1].__url__.count('{'):
				swap=routes[j]
				routes[j]=routes[j-1]
				routes[j-1]=swap
				j-=1
			i+=1
		return routes
	@classmethod
	def sort_none_variable_routes(cls,routes):
		route_length=len(routes)
		i=0
		while i<route_length:
			j=i
			while j>0 and routes[j].__url__.count('/')<=routes[j-1].__url__.count('/'):
				if routes[j].__url__.count('/')<routes[j-1].__url__.count('/'):
					swap=routes[j]
					routes[j]=routes[j-1]
					routes[j-1]=swap
				else:
					if len(routes[j].__url__)<len(routes[j-1].__url__):
						swap=routes[j]
						routes[j]=routes[j-1]
						routes[j-1]=swap
				j-=1
			i+=1
		return routes

	@classmethod
	def process_routes(cls,app,routes):
		for handler in routes:
			_method=getattr(handler,'__method__',None)
			_path=getattr(handler,'__url__',None)
			if _path is None or _method is None:
				raise ValueError("__method__ or __url__ not define in %s."%str(handler.__name__))
			if not asyncio.iscoroutinefunction(handler) and not inspect.isgeneratorfunction(handler):
				handler=asyncio.coroutine(handler)
			if len(_path)>1 and _path.endswith('/'):
				app.router.add_route(_method,_path.rsplit('/',1)[0],BaseHandler(app,handler))
				app.router.add_route(_method,_path,BaseHandler(app,handler))
			elif not _path.endswith('/'):
				app.router.add_route(_method,_path,BaseHandler(app,handler))
				app.router.add_route(_method,_path+'/',BaseHandler(app,handler))
			else:
				app.router.add_route(_method,_path,BaseHandler(app,handler))
	@classmethod
	def register_route(cls,app):
		Route._none_variable_routes=cls.sort_none_variable_routes(Route._none_variable_routes)
		cls.process_routes(app,Route._none_variable_routes)
		Route._incomplete_variable_routes=cls.sort_variable_routes(Route._incomplete_variable_routes)
		cls.process_routes(app,Route._incomplete_variable_routes)
		Route._complete_variable_routes=cls.sort_variable_routes(Route._complete_variable_routes)
		cls.process_routes(app,Route._complete_variable_routes)
		app.router.add_static(Config.app.static_prefix,os.path.join(os.path.dirname(os.path.dirname(__file__)),Config.app.static_path))
if __name__=='__main__':
	@Route.get('/uer/profile')
	def user_profile(name):
		print(name)
	@Route.post('/usr/gallery')
	def user_gallery(name):
		print(name)
	#Route.register_route()
	#Route.register_route()
<commit_msg>fix template not found error in set_status()<commit_after>#-*- coding:utf -*-

import functools
import inspect
import re
import logging
import json
logging.basicConfig(level=logging.INFO)
from   tools.log import Log
from   tools.session import SessionManager
from   tools.config import Config
import os
try:
	import asyncio
except ImportError:
	logging.error("Can't Found Module asyncio")
	exit()
try:
	import aiohttp
	import aiohttp.web
	import aiohttp.errors
	from aiohttp import web
except ImportError:
	logging.error("Can't Found Module aiohttp")
	exit()
try:
	import jinja2
except ImportError:
	logging.error("can't import 'jinja2' module")
	exit()
class AppContainer(dict):
	def __init__(self,app,**kw):
		self._post=app['post']
		self._get=app['get']
		self._app=app
		self._cookie=app['cookie']
		self._app['set_cookie']=[]
		self._app['del_cookie']=[]
		self._app['response']=''
		self._app['redirect']=''
		self._app['status']=''
		self._config=Config
		super(AppContainer,self).__init__(**kw)
	def get_argument(self,name,default=None):
		if name not  in self._post and name not in self._get:
			return default
		if name in self._post:
			return self._post[name]
		if name in self._get:
			return self._get[name]
	def get_all_cookies(self):
		return self._cookie
	def get_cookie(self,cookie_name,default=None):
		if cookie_name in self._cookie:
			return self._cookie[cookie_name]
		return default
	def set_cookie(self,cookie_name,cookie_value,expire=None,*,domain=None,max_age=None,httponly=False,path='/'):
		self._app['set_cookie'].append({'cookie_name':cookie_name,'cookie_value':cookie_value,
'expire':expire,'domain':domain,'path':path,'max-age':max_age,'httponly':httponly})
	def clear_cookie(self,name,*,path='/',domain=None):
		self._app['del_cookie'].append({'cookie_name':name,'path':path,'domain':domain})

	def clear_all_cookies(self):
		if self._cookie:
			for ck in self._cookie:
				self.clear_cookie(ck)
	def render(self,content,**kw):
		if re.match('^[\w]+.html$',content):
			self._app['response']={'__template__':content,'parameter':kw}
		else:
			self._app['response']=content
	@property
	def session(self):
		if not hasattr(self,'_session_instance'):
			session_id=self.get_cookie('ssnid')
			if not session_id:
				session_id=self.get_argument("ssnid")
			if not session_id:
				self._session_instance=SessionManager(driver=self._config.session.driver_name,config=self._config.session.all)
			else:
				self._session_instance=SessionManager(session_id,driver=self._config.session.driver_name,config=self._config.session.all)
		return self._session_instance
	def session_end(self,expire=None):
		if hasattr(self,'_session_instance'):
			self.set_cookie('ssnid',self._session_instance.session_id)
			self._session_instance.save(expire)
	def session_destroy(self,session_id=None):
		if session_id:
			if not hasattr(self,'_session_instance'):
				self._session_instance=SessionManager(driver=self._config.session.driver_name,config=self._config.session.all)
			self._session_instance.delete(session_id)
		else:
			session_id=self.get_cookie("ssnid")
			if  session_id:
				self.clear_cookie('ssnid')
				if not hasattr(self,'_session_instance'):
					self._session_instance=SessionManager(driver=self._config.session.driver_name,config=self._config.session.all)
				self._session_instance.delete(session_id)
	def auth(self,auth=False):
		if auth:
			user_id=self.session[self._config.authentication.auth_id]
			if not user_id:
				self.redirect(self._config.authentication.login_url)
	def redirect(self,url):
		self._app['redirect']=url
	def set_status(self,code,*,message=None):
		assert isinstance(code,int)
		if message:
			self._app['status']={'code':code,'message':message}
		else:
			error_template='errors/'+str(code)+'.html'
			try:
				error_page=self._app['__templating__'].get_template(error_template).render()
			except jinja2.exceptions.TemplateNotFound:
				error_page="none"
			self._app['status']={'code':code,'message':error_page}
class BaseHandler(object):
	r'''
			basic handler process url paramter

	'''
	def __init__(self,app,handlerfn):
		self._app=app
		self._handler=handlerfn
	def _param_generator(self,l):
		def _generator():
			for k in l:
				yield k
		return _generator
	@asyncio.coroutine
	def __call__(self,request):
		post=yield from request.post()
		get=request.GET
		cookie=request.cookies
		self._app['cookie']=request.cookies if request.cookies else {}
		self._app['get']=request.GET if request.GET else {}
		self._app['post']=post if post else {}
		container=AppContainer(app=self._app)
		container.auth(self._handler.__auth__)
		args=self._handler.__args__
		if len(args)==1:
			response=yield from self._handler(container)
		elif len(args)>1:
			param={}
			for k in args[1:]:
				if k not in request.match_info :
					raise NameError("Can't Found '%s'"%k)
				param[k]=request.match_info[k]
			param[self._handler.__args__[0]]=container
			response=yield from self._handler(**param)
		else:
			response=None
		return response

class Middleware(object):
	def http_error_handler(app,handler):
		@asyncio.coroutine
		def _handler(request):
			res=yield from handler(request)
			if app.get('status'):
				res=web.Response(status=app.get('status').get('code'),body=app.get('status').get('message').encode('utf-8'))
				return res
			return res
		return _handler
	def response(app,handler):
		def check_set_cookie(res):
			if len(app['set_cookie'])>0:
				for k in app['set_cookie']:
					res.set_cookie(k['cookie_name'],k['cookie_value'],path=k['path'],expires=k['expire'],domain=k['domain'],httponly=k['httponly'])
			return res
		def check_del_cookie(res):
			if len(app['del_cookie'])>0:
				for k in app['del_cookie']:
					res.del_cookie(k['cookie_name'],path=k['path'],domain=k['domain'])
			return res
		@asyncio.coroutine
		def _response(request):
			res=yield from handler(request)
			res=res if res else app.get('response')
			if app.get('redirect'):
				redirect_url=app.get('redirect')
				app['redirect']=''
				res= aiohttp.web.HTTPFound(redirect_url)
				check_set_cookie(res)
				check_del_cookie(res)
				return res
			if isinstance(res,web.StreamResponse):
				res=res
			elif isinstance(res,bytes):
				res=web.Response(body=res)
				res.content_type='application/octet-stream'
			elif isinstance(res,str):
				res=web.Response(body=res.encode("utf-8"))
				res.content_type='text/html;charset=utf-8'
			elif isinstance(res,dict):
				template=res.get('__template__')
				if template is None:
					res=web.Response(body=json.dumps(res,ensure_ascii=False,default=lambda x:x.__dict__).encode("utf-8"))
					res.content_type='application/json;charset=utf-8'
				else:
					res=web.Response(body=app['__templating__'].get_template(template).render(**res['parameter']).encode("utf-8"))
					res.content_type='text/html;charset=utf-8'
			else:
				res=res
			res=check_set_cookie(res)
			res=check_del_cookie(res)
			return res
		return _response
	def log(app,handler):
		@asyncio.coroutine
		def _log(request):
			Log.info("%s:%s===>%s"%(request.host,request.method,request))
			return (yield from handler(request))
		return _log
	@classmethod
	def allmiddlewares(cls):
		middlewares=list()
		for k,v in cls.__dict__.items():
			if k.startswith('__') and k.endswith('__') or k=='allmiddlewares':
				continue
			if not asyncio.iscoroutinefunction(v):
				v=asyncio.coroutine(v)
			middlewares.append(v)
		return middlewares

class Route(object):
	r'''
		Route class is responsible for routes adding and routes registering to  aiohttp
	'''
	_none_variable_routes=list()
	_incomplete_variable_routes=list()
	_complete_variable_routes=list()
	def __init__(self):
		pass
	@classmethod
	def add_routes(cls,wrapper):
		if wrapper.__url__.count('{')!=0:
			if wrapper.__url__.endswith('/'):
				wrapper.__url__=wrapper.__url__[:wrapper.__url__.rindex('/')]
			if wrapper.__url__.count('{')<wrapper.__url__.count('/'):
				Route._incomplete_variable_routes.append(wrapper)
			else:
				Route._complete_variable_routes.append(wrapper)
		else:
			Route._none_variable_routes.append(wrapper)
	@classmethod
	def get(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='GET'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			cls.add_routes(wrapper)
			return wrapper
		return decorator
	@classmethod
	def post(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='POST'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			cls.add_routes(wrapper)
			return wrapper
		return decorator
	@classmethod
	def put(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='PUT'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			cls.add_routes(wrapper)
			return wrapper
		return decorator
	@classmethod
	def delete(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='DELETE'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			cls.add_routes(wrapper)
			return wrapper
		return decorator
	@classmethod
	def sort_variable_routes(cls,routes):
		route_length=len(routes)
		i=0
		while i<route_length:
			j=i
			while j>0 and routes[j].__url__.count('{')<routes[j-1].__url__.count('{'):
				swap=routes[j]
				routes[j]=routes[j-1]
				routes[j-1]=swap
				j-=1
			i+=1
		return routes
	@classmethod
	def sort_none_variable_routes(cls,routes):
		route_length=len(routes)
		i=0
		while i<route_length:
			j=i
			while j>0 and routes[j].__url__.count('/')<=routes[j-1].__url__.count('/'):
				if routes[j].__url__.count('/')<routes[j-1].__url__.count('/'):
					swap=routes[j]
					routes[j]=routes[j-1]
					routes[j-1]=swap
				else:
					if len(routes[j].__url__)<len(routes[j-1].__url__):
						swap=routes[j]
						routes[j]=routes[j-1]
						routes[j-1]=swap
				j-=1
			i+=1
		return routes

	@classmethod
	def process_routes(cls,app,routes):
		for handler in routes:
			_method=getattr(handler,'__method__',None)
			_path=getattr(handler,'__url__',None)
			if _path is None or _method is None:
				raise ValueError("__method__ or __url__ not define in %s."%str(handler.__name__))
			if not asyncio.iscoroutinefunction(handler) and not inspect.isgeneratorfunction(handler):
				handler=asyncio.coroutine(handler)
			if len(_path)>1 and _path.endswith('/'):
				app.router.add_route(_method,_path.rsplit('/',1)[0],BaseHandler(app,handler))
				app.router.add_route(_method,_path,BaseHandler(app,handler))
			elif not _path.endswith('/'):
				app.router.add_route(_method,_path,BaseHandler(app,handler))
				app.router.add_route(_method,_path+'/',BaseHandler(app,handler))
			else:
				app.router.add_route(_method,_path,BaseHandler(app,handler))
	@classmethod
	def register_route(cls,app):
		Route._none_variable_routes=cls.sort_none_variable_routes(Route._none_variable_routes)
		cls.process_routes(app,Route._none_variable_routes)
		Route._incomplete_variable_routes=cls.sort_variable_routes(Route._incomplete_variable_routes)
		cls.process_routes(app,Route._incomplete_variable_routes)
		Route._complete_variable_routes=cls.sort_variable_routes(Route._complete_variable_routes)
		cls.process_routes(app,Route._complete_variable_routes)
		app.router.add_static(Config.app.static_prefix,os.path.join(os.path.dirname(os.path.dirname(__file__)),Config.app.static_path))
if __name__=='__main__':
	@Route.get('/uer/profile')
	def user_profile(name):
		print(name)
	@Route.post('/usr/gallery')
	def user_gallery(name):
		print(name)
	#Route.register_route()
	#Route.register_route()
<|endoftext|>


<commit_before>#-*- coding:utf -*-

import functools
import inspect
import re
import logging
import json
logging.basicConfig(level=logging.INFO)
from   tools.log import Log
from   tools.session import SessionManager
from   tools.config import Config
import aiohttp.web
import os
try:
	import asyncio
except ImportError:
	logging.error("Can't Found Module asyncio")

try:
   import aiohttp
   from aiohttp import web
except ImportError:
	logging.error("Can't Found Module aiohttp")

class AppContainer(dict):
	def __init__(self,app,**kw):
		self._post=app['post']
		self._get=app['get']
		self._app=app
		self._cookie=app['cookie']
		self._app['set_cookie']=[]
		self._app['del_cookie']=[]
		self._app['response']=''
		self._app['redirect']=''
		self._config=Config
		super(AppContainer,self).__init__(**kw)
	def get_argument(self,name,default=None):
		if name not  in self._post and name not in self._get:
			return default
		if name in self._post:
			return self._post[name]
		if name in self._get:
			return self._get[name]
	def get_all_cookies(self):
		return self._cookie
	def get_cookie(self,cookie_name,default=None):
		if cookie_name in self._cookie:
			return self._cookie[cookie_name]
		return default
	def set_cookie(self,cookie_name,cookie_value,expire=None,*,domain=None,max_age=None,httponly=False,path='/'):
		self._app['set_cookie'].append({'cookie_name':cookie_name,'cookie_value':cookie_value,
'expire':expire,'domain':domain,'path':path,'max-age':max_age,'httponly':httponly})
	def clear_cookie(self,name,*,path='/',domain=None):
		self._app['del_cookie'].append({'cookie_name':name,'path':path,'domain':domain})

	def clear_all_cookies(self):
		if self._cookie:
			for ck in self._cookie:
				self.clear_cookie(ck)
	def render(self,content,**kw):
		if re.match('^[\w]+.html$',content):
			self._app['response']={'__template__':content,'parameter':kw if kw else {}}
		else:
			self._app['response']=content
	@property
	def session(self):
		if not hasattr(self,'_session_instance'):
			session_id=self.get_cookie('ssnid')
			if not session_id:
				session_id=self.get_argument("ssnid")
			if not session_id:
				self._session_instance=SessionManager(driver=self._config.session.driver_name,config=self._config.session.all)
			else:
				self._session_instance=SessionManager(session_id,driver=self._config.session.driver_name,config=self._config.session.all)
		return self._session_instance
	def session_end(self,expire=None):
		if hasattr(self,'_session_instance'):
			self.set_cookie('ssnid',self._session_instance.session_id)
			self._session_instance.save(expire)
	def session_destroy(self,session_id=None):
		if session_id:
			if not hasattr(self,'_session_instance'):
				self._session_instance=SessionManager(driver=self._config.session.driver_name,config=self._config.session.all)
			self._session_instance.delete(session_id)
		else:
			session_id=self.get_cookie("ssnid")
			if  session_id:
				self.clear_cookie('ssnid')
				if not hasattr(self,'_session_instance'):
					self._session_instance=SessionManager(driver=self._config.session.driver_name,config=self._config.session.all)
				self._session_instance.delete(session_id)
	def auth(self,auth=False):
		if auth:
			user_id=self.session[self._config.authentication.auth_id]
			if not user_id:
				self.redirect(self._config.authentication.login_url)
	def redirect(self,url):
		self._app['redirect']=url
class BaseHandler(object):
	r'''
			basic handler process url paramter

	'''
	def __init__(self,app,handlerfn):
		self._app=app
		self._handler=handlerfn
	def _param_generator(self,l):
		def _generator():
			for k in l:
				yield k
		return _generator
	@asyncio.coroutine
	def __call__(self,request):
		post=yield from request.post()
		get=request.GET
		cookie=request.cookies
		self._app['cookie']=request.cookies if request.cookies else {}
		self._app['get']=request.GET if request.GET else {}
		self._app['post']=post if post else {}
		container=AppContainer(app=self._app)
		container.auth(self._handler.__auth__)
		args=self._handler.__args__
		if len(args)==1:
			response=yield from self._handler(container)
		elif len(args)>1:
			param={}
			for k in args[1:]:
				if k not in request.match_info :
					raise NameError("Can't Found '%s'"%k)
				param[k]=request.match_info[k]
			param[self._handler.__args__[0]]=container
			response=yield from self._handler(**param)
		else:
			response=None
		return response

class Middleware(object):
	def response(app,handler):
		def check_set_cookie(res):
			if len(app['set_cookie'])>0:
				for k in app['set_cookie']:
					res.set_cookie(k['cookie_name'],k['cookie_value'],path=k['path'],expires=k['expire'],domain=k['domain'],httponly=k['httponly'])
			return res
		def check_del_cookie(res):
			if len(app['del_cookie'])>0:
				for k in app['del_cookie']:
					res.del_cookie(k['cookie_name'],path=k['path'],domain=k['domain'])
			return res
		@asyncio.coroutine
		def _response(request):
			res=yield from handler(request)
			res=res if res else app.get('response')
			if app.get('redirect'):
				redirect_url=app.get('redirect')
				app['redirect']=''
				return aiohttp.web.HTTPFound(redirect_url)
			if isinstance(res,web.StreamResponse):
				res=res
			elif isinstance(res,bytes):
				res=web.Response(body=res)
				res.content_type='application/octet-stream'
			elif isinstance(res,str):
				res=web.Response(body=res.encode("utf-8"))
				res.content_type='text/html;charset=utf-8'
			elif isinstance(res,dict):
				template=res.get('__template__')
				if template is None:
					res=web.Response(body=json.dumps(res,ensure_ascii=False,default=lambda x:x.__dict__).encode("utf-8"))
					res.content_type='application/json;charset=utf-8'
				else:
					res=web.Response(body=app['__templating__'].get_template(template).render(**res['parameter']).encode("utf-8"))
					res.content_type='text/html;charset=utf-8'
			else:
				res=res
			res=check_set_cookie(res)
			res=check_del_cookie(res)
			return res
		return _response
	def log(app,handler):
		@asyncio.coroutine
		def _log(request):
			Log.info("%s:%s===>%s"%(request.host,request.method,request))
			return (yield from handler(request))
		return _log
	@classmethod
	def allmiddlewares(cls):
		middlewares=list()
		for k,v in cls.__dict__.items():
			if k.startswith('__') and k.endswith('__') or k=='allmiddlewares':
				continue
			if not asyncio.iscoroutinefunction(v):
				v=asyncio.coroutine(v)
			middlewares.append(v)
		return middlewares

class Route(object):
	r'''
		Route class is responsible for routes adding and routes registering to  aiohttp
	'''
	_routes=set()
	def __init__(self):
		pass
	@classmethod
	def get(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='GET'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			Route._routes.add(wrapper)
			return wrapper
		return decorator
	@classmethod
	def post(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='POST'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			Route._routes.add(wrapper)
			return wrapper
		return decorator
	@classmethod
	def put(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='PUT'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			Route._routes.add(wrapper)
			return wrapper
		return decorator
	@classmethod
	def delete(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='DELETE'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			Route._routes.add(wrapper)
			return wrapper
		return decorator
	@classmethod
	def register_route(cls,app):
		for handler in Route._routes:
			_method=getattr(handler,'__method__',None)
			_path=getattr(handler,'__url__',None)
			if _path is None or _method is None:
				raise ValueError('_path or _method not defined in %s.'%str(handler))
			if not asyncio.iscoroutinefunction(handler) and not inspect.isgeneratorfunction(handler):
				handler=asyncio.coroutine(handler)
			app.router.add_route(_method,_path,BaseHandler(app,handler))
			app.router.add_static(Config.app.static_prefix,os.path.join(os.path.dirname(os.path.dirname(__file__)),Config.app.static_path))
			#handler('Jell')
			#print(handler.__method__)
			#print(handler.__url__)
if __name__=='__main__':
	@Route.get('/uer/profile')
	def user_profile(name):
		print(name)
	@Route.post('/usr/gallery')
	def user_gallery(name):
		print(name)
	#Route.register_route()
	#Route.register_route()
<commit_msg>fix routing error for not end with '/'<commit_after>#-*- coding:utf -*-

import functools
import inspect
import re
import logging
import json
logging.basicConfig(level=logging.INFO)
from   tools.log import Log
from   tools.session import SessionManager
from   tools.config import Config
import aiohttp.web
import os
try:
	import asyncio
except ImportError:
	logging.error("Can't Found Module asyncio")

try:
   import aiohttp
   from aiohttp import web
except ImportError:
	logging.error("Can't Found Module aiohttp")

class AppContainer(dict):
	def __init__(self,app,**kw):
		self._post=app['post']
		self._get=app['get']
		self._app=app
		self._cookie=app['cookie']
		self._app['set_cookie']=[]
		self._app['del_cookie']=[]
		self._app['response']=''
		self._app['redirect']=''
		self._config=Config
		super(AppContainer,self).__init__(**kw)
	def get_argument(self,name,default=None):
		if name not  in self._post and name not in self._get:
			return default
		if name in self._post:
			return self._post[name]
		if name in self._get:
			return self._get[name]
	def get_all_cookies(self):
		return self._cookie
	def get_cookie(self,cookie_name,default=None):
		if cookie_name in self._cookie:
			return self._cookie[cookie_name]
		return default
	def set_cookie(self,cookie_name,cookie_value,expire=None,*,domain=None,max_age=None,httponly=False,path='/'):
		self._app['set_cookie'].append({'cookie_name':cookie_name,'cookie_value':cookie_value,
'expire':expire,'domain':domain,'path':path,'max-age':max_age,'httponly':httponly})
	def clear_cookie(self,name,*,path='/',domain=None):
		self._app['del_cookie'].append({'cookie_name':name,'path':path,'domain':domain})

	def clear_all_cookies(self):
		if self._cookie:
			for ck in self._cookie:
				self.clear_cookie(ck)
	def render(self,content,**kw):
		if re.match('^[\w]+.html$',content):
			self._app['response']={'__template__':content,'parameter':kw if kw else {}}
		else:
			self._app['response']=content
	@property
	def session(self):
		if not hasattr(self,'_session_instance'):
			session_id=self.get_cookie('ssnid')
			if not session_id:
				session_id=self.get_argument("ssnid")
			if not session_id:
				self._session_instance=SessionManager(driver=self._config.session.driver_name,config=self._config.session.all)
			else:
				self._session_instance=SessionManager(session_id,driver=self._config.session.driver_name,config=self._config.session.all)
		return self._session_instance
	def session_end(self,expire=None):
		if hasattr(self,'_session_instance'):
			self.set_cookie('ssnid',self._session_instance.session_id)
			self._session_instance.save(expire)
	def session_destroy(self,session_id=None):
		if session_id:
			if not hasattr(self,'_session_instance'):
				self._session_instance=SessionManager(driver=self._config.session.driver_name,config=self._config.session.all)
			self._session_instance.delete(session_id)
		else:
			session_id=self.get_cookie("ssnid")
			if  session_id:
				self.clear_cookie('ssnid')
				if not hasattr(self,'_session_instance'):
					self._session_instance=SessionManager(driver=self._config.session.driver_name,config=self._config.session.all)
				self._session_instance.delete(session_id)
	def auth(self,auth=False):
		if auth:
			user_id=self.session[self._config.authentication.auth_id]
			if not user_id:
				self.redirect(self._config.authentication.login_url)
	def redirect(self,url):
		self._app['redirect']=url
class BaseHandler(object):
	r'''
			basic handler process url paramter

	'''
	def __init__(self,app,handlerfn):
		self._app=app
		self._handler=handlerfn
	def _param_generator(self,l):
		def _generator():
			for k in l:
				yield k
		return _generator
	@asyncio.coroutine
	def __call__(self,request):
		post=yield from request.post()
		get=request.GET
		cookie=request.cookies
		self._app['cookie']=request.cookies if request.cookies else {}
		self._app['get']=request.GET if request.GET else {}
		self._app['post']=post if post else {}
		container=AppContainer(app=self._app)
		container.auth(self._handler.__auth__)
		args=self._handler.__args__
		if len(args)==1:
			response=yield from self._handler(container)
		elif len(args)>1:
			param={}
			for k in args[1:]:
				if k not in request.match_info :
					raise NameError("Can't Found '%s'"%k)
				param[k]=request.match_info[k]
			param[self._handler.__args__[0]]=container
			response=yield from self._handler(**param)
		else:
			response=None
		return response

class Middleware(object):
	def response(app,handler):
		def check_set_cookie(res):
			if len(app['set_cookie'])>0:
				for k in app['set_cookie']:
					res.set_cookie(k['cookie_name'],k['cookie_value'],path=k['path'],expires=k['expire'],domain=k['domain'],httponly=k['httponly'])
			return res
		def check_del_cookie(res):
			if len(app['del_cookie'])>0:
				for k in app['del_cookie']:
					res.del_cookie(k['cookie_name'],path=k['path'],domain=k['domain'])
			return res
		@asyncio.coroutine
		def _response(request):
			res=yield from handler(request)
			res=res if res else app.get('response')
			if app.get('redirect'):
				redirect_url=app.get('redirect')
				app['redirect']=''
				return aiohttp.web.HTTPFound(redirect_url)
			if isinstance(res,web.StreamResponse):
				res=res
			elif isinstance(res,bytes):
				res=web.Response(body=res)
				res.content_type='application/octet-stream'
			elif isinstance(res,str):
				res=web.Response(body=res.encode("utf-8"))
				res.content_type='text/html;charset=utf-8'
			elif isinstance(res,dict):
				template=res.get('__template__')
				if template is None:
					res=web.Response(body=json.dumps(res,ensure_ascii=False,default=lambda x:x.__dict__).encode("utf-8"))
					res.content_type='application/json;charset=utf-8'
				else:
					res=web.Response(body=app['__templating__'].get_template(template).render(**res['parameter']).encode("utf-8"))
					res.content_type='text/html;charset=utf-8'
			else:
				res=res
			res=check_set_cookie(res)
			res=check_del_cookie(res)
			return res
		return _response
	def log(app,handler):
		@asyncio.coroutine
		def _log(request):
			Log.info("%s:%s===>%s"%(request.host,request.method,request))
			return (yield from handler(request))
		return _log
	@classmethod
	def allmiddlewares(cls):
		middlewares=list()
		for k,v in cls.__dict__.items():
			if k.startswith('__') and k.endswith('__') or k=='allmiddlewares':
				continue
			if not asyncio.iscoroutinefunction(v):
				v=asyncio.coroutine(v)
			middlewares.append(v)
		return middlewares

class Route(object):
	r'''
		Route class is responsible for routes adding and routes registering to  aiohttp
	'''
	_routes=set()
	def __init__(self):
		pass
	@classmethod
	def get(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='GET'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			Route._routes.add(wrapper)
			return wrapper
		return decorator
	@classmethod
	def post(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='POST'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			Route._routes.add(wrapper)
			return wrapper
		return decorator
	@classmethod
	def put(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='PUT'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			Route._routes.add(wrapper)
			return wrapper
		return decorator
	@classmethod
	def delete(cls,url,*,auth=False):
		def decorator(func):
			@functools.wraps(func)
			def wrapper(*args,**kw):
				return func(*args,**kw)
			wrapper.__method__='DELETE'
			wrapper.__url__=url
			wrapper.__auth__=auth
			wrapper.__args__=inspect.getargspec(func)[0]
			Route._routes.add(wrapper)
			return wrapper
		return decorator
	@classmethod
	def register_route(cls,app):
		for handler in Route._routes:
			_method=getattr(handler,'__method__',None)
			_path=getattr(handler,'__url__',None)
			if _path is None or _method is None:
				raise ValueError('_path or _method not defined in %s.'%str(handler))
			if not asyncio.iscoroutinefunction(handler) and not inspect.isgeneratorfunction(handler):
				handler=asyncio.coroutine(handler)
			if len(_path)>1 and _path.endswith('/'):
				app.router.add_route(_method,_path.rsplit('/',1)[0],BaseHandler(app,handler))
				app.router.add_route(_method,_path,BaseHandler(app,handler))
			elif not _path.endswith('/'):
				app.router.add_route(_method,_path,BaseHandler(app,handler))
				app.router.add_route(_method,_path+'/',BaseHandler(app,handler))
			else:
				pass
		app.router.add_static(Config.app.static_prefix,os.path.join(os.path.dirname(os.path.dirname(__file__)),Config.app.static_path))
			#handler('Jell')
			#print(handler.__method__)
			#print(handler.__url__)
if __name__=='__main__':
	@Route.get('/uer/profile')
	def user_profile(name):
		print(name)
	@Route.post('/usr/gallery')
	def user_gallery(name):
		print(name)
	#Route.register_route()
	#Route.register_route()
<|endoftext|>