packages: vendor authomatic to provide bitbucket oath2 capabilities.
- regular release doesn't have it yet.
This commit is contained in:
parent
569321aa23
commit
483b3813b0
19 changed files with 8603 additions and 23 deletions
|
|
@ -84,17 +84,6 @@ self: super: {
|
|||
license = [ pkgs.lib.licenses.mit ];
|
||||
};
|
||||
};
|
||||
"authomatic" = super.buildPythonPackage {
|
||||
name = "authomatic-0.1.0.post1";
|
||||
doCheck = false;
|
||||
src = fetchurl {
|
||||
url = "https://code.rhodecode.com/upstream/authomatic/artifacts/download/0-4fe9c041-a567-4f84-be4c-7efa2a606d3c.tar.gz?md5=f6bdc3c769688212db68233e8d2b0383";
|
||||
sha256 = "0pc716mva0ym6xd8jwzjbjp8dqxy9069wwwv2aqwb8lyhl4757ab";
|
||||
};
|
||||
meta = {
|
||||
license = [ pkgs.lib.licenses.mit ];
|
||||
};
|
||||
};
|
||||
"babel" = super.buildPythonPackage {
|
||||
name = "babel-1.3";
|
||||
doCheck = false;
|
||||
|
|
@ -920,11 +909,11 @@ self: super: {
|
|||
};
|
||||
};
|
||||
"meld3" = super.buildPythonPackage {
|
||||
name = "meld3-1.0.2";
|
||||
name = "meld3-2.0.0";
|
||||
doCheck = false;
|
||||
src = fetchurl {
|
||||
url = "https://files.pythonhosted.org/packages/45/a0/317c6422b26c12fe0161e936fc35f36552069ba8e6f7ecbd99bbffe32a5f/meld3-1.0.2.tar.gz";
|
||||
sha256 = "0n4mkwlpsqnmn0dm0wm5hn9nkda0nafl0jdy5sdl5977znh59dzp";
|
||||
url = "https://files.pythonhosted.org/packages/00/3b/023446ddc1bf0b519c369cbe88269c30c6a64bd10af4817c73f560c302f7/meld3-2.0.0.tar.gz";
|
||||
sha256 = "1fbyafwi0d54394hkmp65nf6vk0qm4kipf5z60pdp4244rvadz8y";
|
||||
};
|
||||
meta = {
|
||||
license = [ { fullName = "BSD-derived (http://www.repoze.org/LICENSE.txt)"; } ];
|
||||
|
|
@ -1271,11 +1260,11 @@ self: super: {
|
|||
};
|
||||
};
|
||||
"pyasn1" = super.buildPythonPackage {
|
||||
name = "pyasn1-0.4.6";
|
||||
name = "pyasn1-0.4.7";
|
||||
doCheck = false;
|
||||
src = fetchurl {
|
||||
url = "https://files.pythonhosted.org/packages/e3/12/dfffc84b783e280e942409d6b651fe4a5a746433c34589da7362db2c99c6/pyasn1-0.4.6.tar.gz";
|
||||
sha256 = "11mwdsvrbwvjmny40cxa76h81bbc8jfr1prvw6hw7yvg374xawxp";
|
||||
url = "https://files.pythonhosted.org/packages/ca/f8/2a60a2c88a97558bdd289b6dc9eb75b00bd90ff34155d681ba6dbbcb46b2/pyasn1-0.4.7.tar.gz";
|
||||
sha256 = "0146ryp4g09ycy8p3l2vigmgfg42n4gb8whgg8cysrhxr9b56jd9";
|
||||
};
|
||||
meta = {
|
||||
license = [ pkgs.lib.licenses.bsdOriginal ];
|
||||
|
|
@ -1738,7 +1727,6 @@ self: super: {
|
|||
doCheck = true;
|
||||
propagatedBuildInputs = [
|
||||
self."amqp"
|
||||
self."authomatic"
|
||||
self."babel"
|
||||
self."beaker"
|
||||
self."bleach"
|
||||
|
|
@ -1916,11 +1904,11 @@ self: super: {
|
|||
};
|
||||
};
|
||||
"setuptools" = super.buildPythonPackage {
|
||||
name = "setuptools-41.1.0";
|
||||
name = "setuptools-41.2.0";
|
||||
doCheck = false;
|
||||
src = fetchurl {
|
||||
url = "https://files.pythonhosted.org/packages/68/0c/e470db6866aedbff3c4c88faf7f81b90343d8ff32cd68b62db1b65037fb4/setuptools-41.1.0.zip";
|
||||
sha256 = "1a246z6cikg42adqmpswzjp59hkqwr7xxqs7xyags4cr556bh6f5";
|
||||
url = "https://files.pythonhosted.org/packages/d9/ca/7279974e489e8b65003fe618a1a741d6350227fa2bf48d16be76c7422423/setuptools-41.2.0.zip";
|
||||
sha256 = "04k0dp9msmlv3g3zx7f5p8wdjr6hdf5c0bgmczlc4yncwyx6pf36";
|
||||
};
|
||||
meta = {
|
||||
license = [ pkgs.lib.licenses.mit ];
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
## dependencies
|
||||
|
||||
amqp==2.3.1
|
||||
# not released authomatic that has updated some oauth providers
|
||||
https://code.rhodecode.com/upstream/authomatic/artifacts/download/0-4fe9c041-a567-4f84-be4c-7efa2a606d3c.tar.gz?md5=f6bdc3c769688212db68233e8d2b0383#egg=authomatic==0.1.0.post1
|
||||
|
||||
babel==1.3
|
||||
beaker==1.9.1
|
||||
|
|
|
|||
29
rhodecode/lib/_vendor/__init__.py
Normal file
29
rhodecode/lib/_vendor/__init__.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (C) 2012-2019 RhodeCode GmbH
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License, version 3
|
||||
# (only), as published by the Free Software Foundation.
|
||||
#
|
||||
# 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 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/>.
|
||||
#
|
||||
# This program is dual-licensed. If you wish to learn more about the
|
||||
# RhodeCode Enterprise Edition, including its added features, Support services,
|
||||
# and proprietary license terms, please see https://rhodecode.com/licenses/
|
||||
|
||||
# This package contains non rhodecode licensed packages that are
|
||||
# vendored for various reasons
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
vendor_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
sys.path.append(vendor_dir)
|
||||
14
rhodecode/lib/_vendor/authomatic/__init__.py
Executable file
14
rhodecode/lib/_vendor/authomatic/__init__.py
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Helper functions for use with :class:`Authomatic`.
|
||||
|
||||
.. autosummary::
|
||||
:nosignatures:
|
||||
|
||||
authomatic.provider_id
|
||||
|
||||
"""
|
||||
|
||||
from . import six
|
||||
from .core import Authomatic
|
||||
from .core import provider_id
|
||||
282
rhodecode/lib/_vendor/authomatic/adapters.py
Executable file
282
rhodecode/lib/_vendor/authomatic/adapters.py
Executable file
|
|
@ -0,0 +1,282 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Adapters
|
||||
--------
|
||||
|
||||
.. contents::
|
||||
:backlinks: none
|
||||
|
||||
The :func:`authomatic.login` function needs access to functionality like
|
||||
getting the **URL** of the handler where it is being called, getting the
|
||||
**request params** and **cookies** and **writing the body**, **headers**
|
||||
and **status** to the response.
|
||||
|
||||
Since implementation of these features varies across Python web frameworks,
|
||||
the Authomatic library uses **adapters** to unify these differences into a
|
||||
single interface.
|
||||
|
||||
Available Adapters
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you are missing an adapter for the framework of your choice, please
|
||||
open an `enhancement issue <https://github.com/authomatic/authomatic/issues>`_
|
||||
or consider a contribution to this module by
|
||||
:ref:`implementing <implement_adapters>` one by yourself.
|
||||
Its very easy and shouldn't take you more than a few minutes.
|
||||
|
||||
.. autoclass:: DjangoAdapter
|
||||
:members:
|
||||
|
||||
.. autoclass:: Webapp2Adapter
|
||||
:members:
|
||||
|
||||
.. autoclass:: WebObAdapter
|
||||
:members:
|
||||
|
||||
.. autoclass:: WerkzeugAdapter
|
||||
:members:
|
||||
|
||||
.. _implement_adapters:
|
||||
|
||||
Implementing an Adapter
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Implementing an adapter for a Python web framework is pretty easy.
|
||||
|
||||
Do it by subclassing the :class:`.BaseAdapter` abstract class.
|
||||
There are only **six** members that you need to implement.
|
||||
|
||||
Moreover if your framework is based on the |webob|_ or |werkzeug|_ package
|
||||
you can subclass the :class:`.WebObAdapter` or :class:`.WerkzeugAdapter`
|
||||
respectively.
|
||||
|
||||
.. autoclass:: BaseAdapter
|
||||
:members:
|
||||
|
||||
"""
|
||||
|
||||
import abc
|
||||
from authomatic.core import Response
|
||||
|
||||
|
||||
class BaseAdapter(object):
|
||||
"""
|
||||
Base class for platform adapters.
|
||||
|
||||
Defines common interface for WSGI framework specific functionality.
|
||||
|
||||
"""
|
||||
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
@abc.abstractproperty
|
||||
def params(self):
|
||||
"""
|
||||
Must return a :class:`dict` of all request parameters of any HTTP
|
||||
method.
|
||||
|
||||
:returns:
|
||||
:class:`dict`
|
||||
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def url(self):
|
||||
"""
|
||||
Must return the url of the actual request including path but without
|
||||
query and fragment.
|
||||
|
||||
:returns:
|
||||
:class:`str`
|
||||
|
||||
"""
|
||||
|
||||
@abc.abstractproperty
|
||||
def cookies(self):
|
||||
"""
|
||||
Must return cookies as a :class:`dict`.
|
||||
|
||||
:returns:
|
||||
:class:`dict`
|
||||
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def write(self, value):
|
||||
"""
|
||||
Must write specified value to response.
|
||||
|
||||
:param str value:
|
||||
String to be written to response.
|
||||
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def set_header(self, key, value):
|
||||
"""
|
||||
Must set response headers to ``Key: value``.
|
||||
|
||||
:param str key:
|
||||
Header name.
|
||||
|
||||
:param str value:
|
||||
Header value.
|
||||
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def set_status(self, status):
|
||||
"""
|
||||
Must set the response status e.g. ``'302 Found'``.
|
||||
|
||||
:param str status:
|
||||
The HTTP response status.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class DjangoAdapter(BaseAdapter):
|
||||
"""
|
||||
Adapter for the |django|_ framework.
|
||||
"""
|
||||
|
||||
def __init__(self, request, response):
|
||||
"""
|
||||
:param request:
|
||||
An instance of the :class:`django.http.HttpRequest` class.
|
||||
|
||||
:param response:
|
||||
An instance of the :class:`django.http.HttpResponse` class.
|
||||
"""
|
||||
self.request = request
|
||||
self.response = response
|
||||
|
||||
@property
|
||||
def params(self):
|
||||
params = {}
|
||||
params.update(self.request.GET.dict())
|
||||
params.update(self.request.POST.dict())
|
||||
return params
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
return self.request.build_absolute_uri(self.request.path)
|
||||
|
||||
@property
|
||||
def cookies(self):
|
||||
return dict(self.request.COOKIES)
|
||||
|
||||
def write(self, value):
|
||||
self.response.write(value)
|
||||
|
||||
def set_header(self, key, value):
|
||||
self.response[key] = value
|
||||
|
||||
def set_status(self, status):
|
||||
status_code, reason = status.split(' ', 1)
|
||||
self.response.status_code = int(status_code)
|
||||
|
||||
|
||||
class WebObAdapter(BaseAdapter):
|
||||
"""
|
||||
Adapter for the |webob|_ package.
|
||||
"""
|
||||
|
||||
def __init__(self, request, response):
|
||||
"""
|
||||
:param request:
|
||||
A |webob|_ :class:`Request` instance.
|
||||
|
||||
:param response:
|
||||
A |webob|_ :class:`Response` instance.
|
||||
"""
|
||||
self.request = request
|
||||
self.response = response
|
||||
|
||||
# =========================================================================
|
||||
# Request
|
||||
# =========================================================================
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
return self.request.path_url
|
||||
|
||||
@property
|
||||
def params(self):
|
||||
return dict(self.request.params)
|
||||
|
||||
@property
|
||||
def cookies(self):
|
||||
return dict(self.request.cookies)
|
||||
|
||||
# =========================================================================
|
||||
# Response
|
||||
# =========================================================================
|
||||
|
||||
def write(self, value):
|
||||
self.response.write(value)
|
||||
|
||||
def set_header(self, key, value):
|
||||
self.response.headers[key] = str(value)
|
||||
|
||||
def set_status(self, status):
|
||||
self.response.status = status
|
||||
|
||||
|
||||
class Webapp2Adapter(WebObAdapter):
|
||||
"""
|
||||
Adapter for the |webapp2|_ framework.
|
||||
|
||||
Inherits from the :class:`.WebObAdapter`.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, handler):
|
||||
"""
|
||||
:param handler:
|
||||
A :class:`webapp2.RequestHandler` instance.
|
||||
"""
|
||||
self.request = handler.request
|
||||
self.response = handler.response
|
||||
|
||||
|
||||
class WerkzeugAdapter(BaseAdapter):
|
||||
"""
|
||||
Adapter for |flask|_ and other |werkzeug|_ based frameworks.
|
||||
|
||||
Thanks to `Mark Steve Samson <http://marksteve.com>`_.
|
||||
|
||||
"""
|
||||
|
||||
@property
|
||||
def params(self):
|
||||
return self.request.args
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
return self.request.base_url
|
||||
|
||||
@property
|
||||
def cookies(self):
|
||||
return self.request.cookies
|
||||
|
||||
def __init__(self, request, response):
|
||||
"""
|
||||
:param request:
|
||||
Instance of the :class:`werkzeug.wrappers.Request` class.
|
||||
|
||||
:param response:
|
||||
Instance of the :class:`werkzeug.wrappers.Response` class.
|
||||
"""
|
||||
|
||||
self.request = request
|
||||
self.response = response
|
||||
|
||||
def write(self, value):
|
||||
self.response.data = self.response.data.decode('utf-8') + value
|
||||
|
||||
def set_header(self, key, value):
|
||||
self.response.headers[key] = value
|
||||
|
||||
def set_status(self, status):
|
||||
self.response.status = status
|
||||
1764
rhodecode/lib/_vendor/authomatic/core.py
Executable file
1764
rhodecode/lib/_vendor/authomatic/core.py
Executable file
File diff suppressed because it is too large
Load diff
84
rhodecode/lib/_vendor/authomatic/exceptions.py
Executable file
84
rhodecode/lib/_vendor/authomatic/exceptions.py
Executable file
|
|
@ -0,0 +1,84 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Provides various exception types for the library.
|
||||
"""
|
||||
|
||||
|
||||
class BaseError(Exception):
|
||||
"""
|
||||
Base error for all errors.
|
||||
"""
|
||||
|
||||
def __init__(self, message, original_message='', url='', status=None):
|
||||
super(BaseError, self).__init__(message)
|
||||
|
||||
#: Error message.
|
||||
self.message = message
|
||||
|
||||
#: Original message.
|
||||
self.original_message = original_message
|
||||
|
||||
#: URL related with the error.
|
||||
self.url = url
|
||||
|
||||
#: HTTP status code related with the error.
|
||||
self.status = status
|
||||
|
||||
def to_dict(self):
|
||||
return self.__dict__
|
||||
|
||||
|
||||
class ConfigError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class SessionError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class CredentialsError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class HTTPError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class CSRFError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class ImportStringError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class AuthenticationError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class OAuth1Error(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class OAuth2Error(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class OpenIDError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class CancellationError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class FailureError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class FetchError(BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class RequestElementsError(BaseError):
|
||||
pass
|
||||
0
rhodecode/lib/_vendor/authomatic/extras/__init__.py
Executable file
0
rhodecode/lib/_vendor/authomatic/extras/__init__.py
Executable file
47
rhodecode/lib/_vendor/authomatic/extras/flask.py
Executable file
47
rhodecode/lib/_vendor/authomatic/extras/flask.py
Executable file
|
|
@ -0,0 +1,47 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
|flask| Extras
|
||||
--------------
|
||||
|
||||
Utilities you can use when using this library with the |flask|_ framework.
|
||||
|
||||
Thanks to `Mark Steve Samson <http://marksteve.com>`_.
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from functools import wraps
|
||||
|
||||
from authomatic.adapters import WerkzeugAdapter
|
||||
from authomatic import Authomatic
|
||||
from flask import make_response, request, session
|
||||
|
||||
|
||||
class FlaskAuthomatic(Authomatic):
|
||||
"""
|
||||
Flask Plugin for authomatic support.
|
||||
"""
|
||||
|
||||
result = None
|
||||
|
||||
def login(self, *login_args, **login_kwargs):
|
||||
"""
|
||||
Decorator for Flask view functions.
|
||||
"""
|
||||
|
||||
def decorator(f):
|
||||
@wraps(f)
|
||||
def decorated(*args, **kwargs):
|
||||
self.response = make_response()
|
||||
adapter = WerkzeugAdapter(request, self.response)
|
||||
login_kwargs.setdefault('session', session)
|
||||
login_kwargs.setdefault('session_saver', self.session_saver)
|
||||
self.result = super(FlaskAuthomatic, self).login(
|
||||
adapter,
|
||||
*login_args,
|
||||
**login_kwargs)
|
||||
return f(*args, **kwargs)
|
||||
return decorated
|
||||
return decorator
|
||||
|
||||
def session_saver(self):
|
||||
session.modified = True
|
||||
241
rhodecode/lib/_vendor/authomatic/extras/gae/__init__.py
Executable file
241
rhodecode/lib/_vendor/authomatic/extras/gae/__init__.py
Executable file
|
|
@ -0,0 +1,241 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
|gae| Extras
|
||||
------------
|
||||
|
||||
Utilities you can use when using this library on |gae|_.
|
||||
"""
|
||||
|
||||
from google.appengine.ext import ndb
|
||||
from webapp2_extras import sessions
|
||||
|
||||
from authomatic import exceptions
|
||||
from authomatic.extras import interfaces
|
||||
from authomatic.extras.gae.openid import NDBOpenIDStore
|
||||
|
||||
|
||||
__all__ = ['ndb_config', 'Webapp2Session']
|
||||
|
||||
|
||||
class GAEError(exceptions.BaseError):
|
||||
pass
|
||||
|
||||
|
||||
class Webapp2Session(interfaces.BaseSession):
|
||||
"""
|
||||
A simple wrapper for |webapp2|_ sessions. If you provide a session it wraps
|
||||
it and adds the :meth:`.save` method.
|
||||
|
||||
If you don't provide a session it creates a new one but you must provide
|
||||
the :data:`.secret`.
|
||||
|
||||
For more about |webapp2| sessions see:
|
||||
http://webapp-improved.appspot.com/api/webapp2_extras/sessions.html.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, handler, session=None, secret=None,
|
||||
cookie_name='webapp2authomatic', backend='memcache',
|
||||
config=None):
|
||||
"""
|
||||
.. warning::
|
||||
|
||||
Do not use the ``'securecookie'`` backend with
|
||||
:class:`.providers.OpenID` provider. The
|
||||
`python-openid`_ library saves **non json serializable** objects
|
||||
to session which the ``'securecookie'`` backend cannot cope with.
|
||||
|
||||
:param handler:
|
||||
A :class:`webapp2.RequestHandler` instance.
|
||||
|
||||
:param session:
|
||||
A :class:`webapp2_extras.session.SessionDict` instance.
|
||||
|
||||
:param str secret:
|
||||
The session secret.
|
||||
|
||||
:param str cookie_name:
|
||||
The name of the session cookie.
|
||||
|
||||
:param backend:
|
||||
The session backend. One of ``'memcache'`` or ``'datastore'``.
|
||||
|
||||
:param config:
|
||||
The session config.
|
||||
|
||||
"""
|
||||
|
||||
self.handler = handler
|
||||
|
||||
if session is None:
|
||||
if not secret:
|
||||
raise GAEError('Either session or secret must be specified!')
|
||||
else:
|
||||
# Create new session.
|
||||
cfg = config or dict(
|
||||
secret_key=secret, cookie_name=cookie_name)
|
||||
session_store = sessions.SessionStore(handler.request, cfg)
|
||||
self.session_dict = session_store.get_session(backend=backend)
|
||||
else:
|
||||
# Use supplied session.
|
||||
self.session_dict = session
|
||||
|
||||
def save(self):
|
||||
return self.session_dict.container.save_session(self.handler.response)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
return self.session_dict.__setitem__(key, value)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self.session_dict.__getitem__(key)
|
||||
|
||||
def __delitem__(self, key):
|
||||
return self.session_dict.__delitem__(key)
|
||||
|
||||
def get(self, key):
|
||||
return self.session_dict.get(key)
|
||||
|
||||
|
||||
class NDBConfig(ndb.Model):
|
||||
"""
|
||||
|gae| `NDB <https://developers.google.com/appengine/docs/python/ndb/>`_
|
||||
based :doc:`config`.
|
||||
|
||||
.. note::
|
||||
|
||||
By :class:`.OpenID` provider uses :class:`.NDBOpenIDStore`
|
||||
as default :attr:`.OpenID.store`.
|
||||
|
||||
"""
|
||||
|
||||
# General properties
|
||||
provider_name = ndb.StringProperty()
|
||||
class_ = ndb.StringProperty()
|
||||
|
||||
# AuthorizationProvider properties
|
||||
provider_id = ndb.IntegerProperty()
|
||||
consumer_key = ndb.StringProperty()
|
||||
consumer_secret = ndb.StringProperty()
|
||||
|
||||
# OAuth2 properties
|
||||
scope = ndb.StringProperty()
|
||||
offline = ndb.BooleanProperty()
|
||||
|
||||
# AuthenticationProvider properties
|
||||
identifier_param = ndb.StringProperty()
|
||||
|
||||
@classmethod
|
||||
def get(cls, key, default=None):
|
||||
"""
|
||||
Resembles the :meth:`dict.get` method.
|
||||
|
||||
:returns:
|
||||
A configuration dictionary for specified provider.
|
||||
|
||||
"""
|
||||
|
||||
# Query datastore.
|
||||
result = cls.query(cls.provider_name == key).get()
|
||||
|
||||
if result:
|
||||
result_dict = result.to_dict()
|
||||
|
||||
# Use NDBOpenIDStore by default
|
||||
result_dict['store'] = NDBOpenIDStore
|
||||
|
||||
# Convert coma-separated values to list. Currently only scope is
|
||||
# csv.
|
||||
for i in ('scope', ):
|
||||
prop = result_dict.get(i)
|
||||
if prop:
|
||||
result_dict[i] = [s.strip() for s in prop.split(',')]
|
||||
else:
|
||||
result_dict[i] = None
|
||||
|
||||
return result_dict
|
||||
else:
|
||||
return default
|
||||
|
||||
@classmethod
|
||||
def values(cls):
|
||||
"""
|
||||
Resembles the :meth:`dict.values` method.
|
||||
"""
|
||||
|
||||
# get all items
|
||||
results = cls.query().fetch()
|
||||
# return list of dictionaries
|
||||
return [result.to_dict() for result in results]
|
||||
|
||||
@classmethod
|
||||
def initialize(cls):
|
||||
"""
|
||||
Creates an **"Example"** entity of kind **"NDBConfig"** in the
|
||||
datastore if the model is empty and raises and error to inform you that
|
||||
you should populate the model with data.
|
||||
|
||||
.. note::
|
||||
|
||||
The *Datastore Viewer* in the ``_ah/admin/`` won't let you add
|
||||
properties to a model if there is not an entity with that
|
||||
property already. Therefore it is a good idea to keep the
|
||||
**"Example"** entity (which has all possible properties set) in
|
||||
the datastore.
|
||||
|
||||
"""
|
||||
|
||||
if not len(cls.query().fetch()):
|
||||
|
||||
example = cls.get_or_insert('Example')
|
||||
|
||||
example.class_ = 'Provider class e.g. ' + \
|
||||
'"authomatic.providers.oauth2.Facebook".'
|
||||
example.provider_name = 'Your custom provider name e.g. "fb".'
|
||||
|
||||
# AuthorizationProvider
|
||||
example.consumer_key = 'Consumer key.'
|
||||
example.consumer_secret = 'Consumer secret'
|
||||
example.provider_id = 1
|
||||
|
||||
# OAuth2
|
||||
example.scope = 'coma, separated, list, of, scopes'
|
||||
|
||||
# AuthenticationProvider
|
||||
example.identifier_param = 'Querystring parameter for claimed ' + \
|
||||
'id. default is "id"'
|
||||
|
||||
# Save the example
|
||||
example.put()
|
||||
|
||||
# Raise an information error.
|
||||
raise GAEError(
|
||||
'A NDBConfig data model was created! Go to Datastore Viewer '
|
||||
'in your dashboard and populate it with data!')
|
||||
|
||||
|
||||
def ndb_config():
|
||||
"""
|
||||
Allows you to have a **datastore** :doc:`config` instead of a hardcoded
|
||||
one.
|
||||
|
||||
This function creates an **"Example"** entity of kind **"NDBConfig"** in
|
||||
the datastore if the model is empty and raises and error to inform you
|
||||
that you should populate the model with data.
|
||||
|
||||
.. note::
|
||||
|
||||
The *Datastore Viewer* of the |gae|_ admin won't let you add
|
||||
properties to a model if there is not an entity with that property
|
||||
already. Therefore it is a good idea to keep the **"Example"**
|
||||
entity (which has all properties set) in the datastore.
|
||||
|
||||
:raises:
|
||||
:exc:`.GAEError`
|
||||
|
||||
:returns:
|
||||
:class:`.NDBConfig`
|
||||
|
||||
"""
|
||||
|
||||
NDBConfig.initialize()
|
||||
return NDBConfig
|
||||
156
rhodecode/lib/_vendor/authomatic/extras/gae/openid.py
Executable file
156
rhodecode/lib/_vendor/authomatic/extras/gae/openid.py
Executable file
|
|
@ -0,0 +1,156 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# We need absolute import to import from openid library which has the same
|
||||
# name as this module
|
||||
from __future__ import absolute_import
|
||||
import logging
|
||||
import datetime
|
||||
|
||||
from google.appengine.ext import ndb
|
||||
import openid.store.interface
|
||||
|
||||
|
||||
class NDBOpenIDStore(ndb.Expando, openid.store.interface.OpenIDStore):
|
||||
"""
|
||||
|gae| `NDB <https://developers.google.com/appengine/docs/python/ndb/>`_
|
||||
based implementation of the :class:`openid.store.interface.OpenIDStore`
|
||||
interface of the `python-openid`_ library.
|
||||
"""
|
||||
|
||||
serialized = ndb.StringProperty()
|
||||
expiration_date = ndb.DateTimeProperty()
|
||||
# we need issued to sort by most recently issued
|
||||
issued = ndb.IntegerProperty()
|
||||
|
||||
@staticmethod
|
||||
def _log(*args, **kwargs):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def storeAssociation(cls, server_url, association):
|
||||
# store an entity with key = server_url
|
||||
|
||||
issued = datetime.datetime.fromtimestamp(association.issued)
|
||||
lifetime = datetime.timedelta(0, association.lifetime)
|
||||
|
||||
expiration_date = issued + lifetime
|
||||
entity = cls.get_or_insert(
|
||||
association.handle, parent=ndb.Key(
|
||||
'ServerUrl', server_url))
|
||||
|
||||
entity.serialized = association.serialize()
|
||||
entity.expiration_date = expiration_date
|
||||
entity.issued = association.issued
|
||||
|
||||
cls._log(
|
||||
logging.DEBUG,
|
||||
u'NDBOpenIDStore: Putting OpenID association to datastore.')
|
||||
|
||||
entity.put()
|
||||
|
||||
@classmethod
|
||||
def cleanupAssociations(cls):
|
||||
# query for all expired
|
||||
cls._log(
|
||||
logging.DEBUG,
|
||||
u'NDBOpenIDStore: Querying datastore for OpenID associations.')
|
||||
query = cls.query(cls.expiration_date <= datetime.datetime.now())
|
||||
|
||||
# fetch keys only
|
||||
expired = query.fetch(keys_only=True)
|
||||
|
||||
# delete all expired
|
||||
cls._log(
|
||||
logging.DEBUG,
|
||||
u'NDBOpenIDStore: Deleting expired OpenID associations from datastore.')
|
||||
ndb.delete_multi(expired)
|
||||
|
||||
return len(expired)
|
||||
|
||||
@classmethod
|
||||
def getAssociation(cls, server_url, handle=None):
|
||||
cls.cleanupAssociations()
|
||||
|
||||
if handle:
|
||||
key = ndb.Key('ServerUrl', server_url, cls, handle)
|
||||
cls._log(
|
||||
logging.DEBUG,
|
||||
u'NDBOpenIDStore: Getting OpenID association from datastore by key.')
|
||||
entity = key.get()
|
||||
else:
|
||||
# return most recently issued association
|
||||
cls._log(
|
||||
logging.DEBUG,
|
||||
u'NDBOpenIDStore: Querying datastore for OpenID associations by ancestor.')
|
||||
entity = cls.query(ancestor=ndb.Key(
|
||||
'ServerUrl', server_url)).order(-cls.issued).get()
|
||||
|
||||
if entity and entity.serialized:
|
||||
return openid.association.Association.deserialize(
|
||||
entity.serialized)
|
||||
|
||||
@classmethod
|
||||
def removeAssociation(cls, server_url, handle):
|
||||
key = ndb.Key('ServerUrl', server_url, cls, handle)
|
||||
cls._log(
|
||||
logging.DEBUG,
|
||||
u'NDBOpenIDStore: Getting OpenID association from datastore by key.')
|
||||
if key.get():
|
||||
cls._log(
|
||||
logging.DEBUG,
|
||||
u'NDBOpenIDStore: Deleting OpenID association from datastore.')
|
||||
key.delete()
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def useNonce(cls, server_url, timestamp, salt):
|
||||
|
||||
# check whether there is already an entity with the same ancestor path
|
||||
# in the datastore
|
||||
key = ndb.Key(
|
||||
'ServerUrl',
|
||||
str(server_url) or 'x',
|
||||
'TimeStamp',
|
||||
str(timestamp),
|
||||
cls,
|
||||
str(salt))
|
||||
|
||||
cls._log(
|
||||
logging.DEBUG,
|
||||
u'NDBOpenIDStore: Getting OpenID nonce from datastore by key.')
|
||||
result = key.get()
|
||||
|
||||
if result:
|
||||
# if so, the nonce is not valid so return False
|
||||
cls._log(
|
||||
logging.WARNING,
|
||||
u'NDBOpenIDStore: Nonce was already used!')
|
||||
return False
|
||||
else:
|
||||
# if not, store the key to datastore and return True
|
||||
nonce = cls(key=key)
|
||||
nonce.expiration_date = datetime.datetime.fromtimestamp(
|
||||
timestamp) + datetime.timedelta(0, openid.store.nonce.SKEW)
|
||||
cls._log(
|
||||
logging.DEBUG,
|
||||
u'NDBOpenIDStore: Putting new nonce to datastore.')
|
||||
nonce.put()
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def cleanupNonces(cls):
|
||||
# get all expired nonces
|
||||
cls._log(
|
||||
logging.DEBUG,
|
||||
u'NDBOpenIDStore: Querying datastore for OpenID nonces ordered by expiration date.')
|
||||
expired = cls.query().filter(
|
||||
cls.expiration_date <= datetime.datetime.now()).fetch(
|
||||
keys_only=True)
|
||||
|
||||
# delete all expired
|
||||
cls._log(
|
||||
logging.DEBUG,
|
||||
u'NDBOpenIDStore: Deleting expired OpenID nonces from datastore.')
|
||||
ndb.delete_multi(expired)
|
||||
|
||||
return len(expired)
|
||||
73
rhodecode/lib/_vendor/authomatic/extras/interfaces.py
Executable file
73
rhodecode/lib/_vendor/authomatic/extras/interfaces.py
Executable file
|
|
@ -0,0 +1,73 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Interfaces
|
||||
^^^^^^^^^^
|
||||
|
||||
If you want to implement framework specific extras, use these abstract
|
||||
classes as bases:
|
||||
|
||||
"""
|
||||
|
||||
import abc
|
||||
|
||||
|
||||
class BaseSession(object):
|
||||
"""
|
||||
Abstract class for custom session implementations.
|
||||
"""
|
||||
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
@abc.abstractmethod
|
||||
def save(self):
|
||||
"""
|
||||
Called only once per request.
|
||||
|
||||
Should implement a mechanism for setting the the session
|
||||
**cookie** and saving the session **data** to storage.
|
||||
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __setitem__(self, key, value):
|
||||
"""
|
||||
Same as :meth:`dict.__setitem__`.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __getitem__(self, key):
|
||||
"""
|
||||
Same as :meth:`dict.__getitem__`.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def __delitem__(self, key):
|
||||
"""
|
||||
Same as :meth:`dict.__delitem__`.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get(self, key):
|
||||
"""
|
||||
Same as :meth:`dict.get`.
|
||||
"""
|
||||
|
||||
|
||||
class BaseConfig(object):
|
||||
"""
|
||||
Abstract class for :doc:`config` implementations.
|
||||
"""
|
||||
|
||||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
@abc.abstractmethod
|
||||
def get(self, key):
|
||||
"""
|
||||
Same as :attr:`dict.get`.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def values(self):
|
||||
"""
|
||||
Same as :meth:`dict.values`.
|
||||
"""
|
||||
1012
rhodecode/lib/_vendor/authomatic/providers/__init__.py
Executable file
1012
rhodecode/lib/_vendor/authomatic/providers/__init__.py
Executable file
File diff suppressed because it is too large
Load diff
112
rhodecode/lib/_vendor/authomatic/providers/gaeopenid.py
Executable file
112
rhodecode/lib/_vendor/authomatic/providers/gaeopenid.py
Executable file
|
|
@ -0,0 +1,112 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Google App Engine OpenID Providers
|
||||
----------------------------------
|
||||
|
||||
|openid|_ provider implementations based on the |gae_users_api|_.
|
||||
|
||||
.. note::
|
||||
|
||||
When using the :class:`GAEOpenID` provider, the :class:`.User` object
|
||||
will always have only the
|
||||
:attr:`.User.user_id`,
|
||||
:attr:`.User.email`,
|
||||
:attr:`.User.gae_user`
|
||||
attributes populated with data.
|
||||
Moreover the :attr:`.User.user_id` will always be empty on the
|
||||
`GAE Development Server
|
||||
<https://developers.google.com/appengine/docs/python/tools/devserver>`_.
|
||||
|
||||
.. autosummary::
|
||||
|
||||
GAEOpenID
|
||||
Yahoo
|
||||
Google
|
||||
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from google.appengine.api import users
|
||||
|
||||
import authomatic.core as core
|
||||
from authomatic import providers
|
||||
from authomatic.exceptions import FailureError
|
||||
|
||||
|
||||
__all__ = ['GAEOpenID', 'Yahoo', 'Google']
|
||||
|
||||
|
||||
class GAEOpenID(providers.AuthenticationProvider):
|
||||
"""
|
||||
|openid|_ provider based on the |gae_users_api|_.
|
||||
|
||||
Accepts additional keyword arguments inherited from
|
||||
:class:`.AuthenticationProvider`.
|
||||
|
||||
"""
|
||||
|
||||
@providers.login_decorator
|
||||
def login(self):
|
||||
"""
|
||||
Launches the OpenID authentication procedure.
|
||||
"""
|
||||
|
||||
if self.params.get(self.identifier_param):
|
||||
# =================================================================
|
||||
# Phase 1 before redirect.
|
||||
# =================================================================
|
||||
self._log(
|
||||
logging.INFO,
|
||||
u'Starting OpenID authentication procedure.')
|
||||
|
||||
url = users.create_login_url(
|
||||
dest_url=self.url, federated_identity=self.identifier)
|
||||
|
||||
self._log(logging.INFO, u'Redirecting user to {0}.'.format(url))
|
||||
|
||||
self.redirect(url)
|
||||
else:
|
||||
# =================================================================
|
||||
# Phase 2 after redirect.
|
||||
# =================================================================
|
||||
|
||||
self._log(
|
||||
logging.INFO,
|
||||
u'Continuing OpenID authentication procedure after redirect.')
|
||||
|
||||
user = users.get_current_user()
|
||||
|
||||
if user:
|
||||
self._log(logging.INFO, u'Authentication successful.')
|
||||
self._log(logging.INFO, u'Creating user.')
|
||||
self.user = core.User(self,
|
||||
id=user.federated_identity(),
|
||||
email=user.email(),
|
||||
gae_user=user)
|
||||
|
||||
# =============================================================
|
||||
# We're done
|
||||
# =============================================================
|
||||
else:
|
||||
raise FailureError(
|
||||
'Unable to authenticate identifier "{0}"!'.format(
|
||||
self.identifier))
|
||||
|
||||
|
||||
class Yahoo(GAEOpenID):
|
||||
"""
|
||||
:class:`.GAEOpenID` provider with the :attr:`.identifier` set to
|
||||
``"me.yahoo.com"``.
|
||||
"""
|
||||
|
||||
identifier = 'me.yahoo.com'
|
||||
|
||||
|
||||
class Google(GAEOpenID):
|
||||
"""
|
||||
:class:`.GAEOpenID` provider with the :attr:`.identifier` set to
|
||||
``"https://www.google.com/accounts/o8/id"``.
|
||||
"""
|
||||
|
||||
identifier = 'https://www.google.com/accounts/o8/id'
|
||||
1377
rhodecode/lib/_vendor/authomatic/providers/oauth1.py
Executable file
1377
rhodecode/lib/_vendor/authomatic/providers/oauth1.py
Executable file
File diff suppressed because it is too large
Load diff
2053
rhodecode/lib/_vendor/authomatic/providers/oauth2.py
Executable file
2053
rhodecode/lib/_vendor/authomatic/providers/oauth2.py
Executable file
File diff suppressed because it is too large
Load diff
505
rhodecode/lib/_vendor/authomatic/providers/openid.py
Executable file
505
rhodecode/lib/_vendor/authomatic/providers/openid.py
Executable file
|
|
@ -0,0 +1,505 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
|openid| Providers
|
||||
----------------------------------
|
||||
|
||||
Providers which implement the |openid|_ protocol based on the
|
||||
`python-openid`_ library.
|
||||
|
||||
.. warning::
|
||||
|
||||
This providers are dependent on the |pyopenid|_ package.
|
||||
|
||||
.. autosummary::
|
||||
|
||||
OpenID
|
||||
Yahoo
|
||||
Google
|
||||
|
||||
"""
|
||||
|
||||
# We need absolute import to import from openid library which has the same
|
||||
# name as this module
|
||||
from __future__ import absolute_import
|
||||
import datetime
|
||||
import logging
|
||||
import time
|
||||
|
||||
from openid import oidutil
|
||||
from openid.consumer import consumer
|
||||
from openid.extensions import ax, pape, sreg
|
||||
from openid.association import Association
|
||||
|
||||
from authomatic import providers
|
||||
from authomatic.exceptions import FailureError, CancellationError, OpenIDError
|
||||
|
||||
|
||||
__all__ = ['OpenID', 'Yahoo', 'Google']
|
||||
|
||||
|
||||
# Suppress openid logging.
|
||||
oidutil.log = lambda message, level=0: None
|
||||
|
||||
|
||||
REALM_HTML = \
|
||||
"""
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="X-XRDS-Location" content="{xrds_location}" />
|
||||
</head>
|
||||
<body>{body}</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
|
||||
XRDS_XML = \
|
||||
"""
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xrds:XRDS
|
||||
xmlns:xrds="xri://$xrds"
|
||||
xmlns:openid="http://openid.net/xmlns/1.0"
|
||||
xmlns="xri://$xrd*($v*2.0)">
|
||||
<XRD>
|
||||
<Service priority="1">
|
||||
<Type>http://specs.openid.net/auth/2.0/return_to</Type>
|
||||
<URI>{return_to}</URI>
|
||||
</Service>
|
||||
</XRD>
|
||||
</xrds:XRDS>
|
||||
"""
|
||||
|
||||
|
||||
class SessionOpenIDStore(object):
|
||||
"""
|
||||
A very primitive session-based implementation of the.
|
||||
|
||||
:class:`openid.store.interface.OpenIDStore` interface of the
|
||||
`python-openid`_ library.
|
||||
|
||||
.. warning::
|
||||
|
||||
Nonces get verified only by their timeout. Use on your own risk!
|
||||
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _log(level, message):
|
||||
return None
|
||||
|
||||
ASSOCIATION_KEY = ('authomatic.providers.openid.SessionOpenIDStore:'
|
||||
'association')
|
||||
|
||||
def __init__(self, session, nonce_timeout=None):
|
||||
"""
|
||||
:param int nonce_timeout:
|
||||
|
||||
Nonces older than this in seconds will be considered expired.
|
||||
Default is 600.
|
||||
"""
|
||||
self.session = session
|
||||
self.nonce_timeout = nonce_timeout or 600
|
||||
|
||||
def storeAssociation(self, server_url, association):
|
||||
self._log(logging.DEBUG,
|
||||
'SessionOpenIDStore: Storing association to session.')
|
||||
|
||||
serialized = association.serialize()
|
||||
decoded = serialized.decode('latin-1')
|
||||
|
||||
assoc = decoded
|
||||
# assoc = serialized
|
||||
|
||||
# Always store only one association as a tuple.
|
||||
self.session[self.ASSOCIATION_KEY] = (server_url, association.handle,
|
||||
assoc)
|
||||
|
||||
def getAssociation(self, server_url, handle=None):
|
||||
# Try to get association.
|
||||
assoc = self.session.get(self.ASSOCIATION_KEY)
|
||||
if assoc and assoc[0] == server_url:
|
||||
# If found deserialize and return it.
|
||||
self._log(logging.DEBUG, u'SessionOpenIDStore: Association found.')
|
||||
return Association.deserialize(assoc[2].encode('latin-1'))
|
||||
else:
|
||||
self._log(logging.DEBUG,
|
||||
u'SessionOpenIDStore: Association not found.')
|
||||
|
||||
def removeAssociation(self, server_url, handle):
|
||||
# Just inform the caller that it's gone.
|
||||
return True
|
||||
|
||||
def useNonce(self, server_url, timestamp, salt):
|
||||
# Evaluate expired nonces as false.
|
||||
age = int(time.time()) - int(timestamp)
|
||||
if age < self.nonce_timeout:
|
||||
return True
|
||||
else:
|
||||
self._log(logging.ERROR, u'SessionOpenIDStore: Expired nonce!')
|
||||
return False
|
||||
|
||||
|
||||
class OpenID(providers.AuthenticationProvider):
|
||||
"""
|
||||
|openid|_ provider based on the `python-openid`_ library.
|
||||
"""
|
||||
|
||||
AX = ['http://axschema.org/contact/email',
|
||||
'http://schema.openid.net/contact/email',
|
||||
'http://axschema.org/namePerson',
|
||||
'http://openid.net/schema/namePerson/first',
|
||||
'http://openid.net/schema/namePerson/last',
|
||||
'http://openid.net/schema/gender',
|
||||
'http://openid.net/schema/language/pref',
|
||||
'http://openid.net/schema/contact/web/default',
|
||||
'http://openid.net/schema/media/image',
|
||||
'http://openid.net/schema/timezone']
|
||||
|
||||
AX_REQUIRED = ['http://schema.openid.net/contact/email']
|
||||
|
||||
SREG = ['nickname',
|
||||
'email',
|
||||
'fullname',
|
||||
'dob',
|
||||
'gender',
|
||||
'postcode',
|
||||
'country',
|
||||
'language',
|
||||
'timezone']
|
||||
|
||||
PAPE = [
|
||||
'http://schemas.openid.net/pape/policies/2007/06/'
|
||||
'multi-factor-physical',
|
||||
'http://schemas.openid.net/pape/policies/2007/06/multi-factor',
|
||||
'http://schemas.openid.net/pape/policies/2007/06/phishing-resistant'
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
Accepts additional keyword arguments:
|
||||
|
||||
:param store:
|
||||
Any object which implements
|
||||
:class:`openid.store.interface.OpenIDStore`
|
||||
of the `python-openid`_ library.
|
||||
|
||||
:param bool use_realm:
|
||||
Whether to use `OpenID realm
|
||||
<http://openid.net/specs/openid-authentication-2_0-12.html#realms>`_
|
||||
If ``True`` the realm HTML document will be accessible at
|
||||
``{current url}?{realm_param}={realm_param}``
|
||||
e.g. ``http://example.com/path?realm=realm``.
|
||||
|
||||
:param str realm_body:
|
||||
Contents of the HTML body tag of the realm.
|
||||
|
||||
:param str realm_param:
|
||||
Name of the query parameter to be used to serve the realm.
|
||||
|
||||
:param str xrds_param:
|
||||
The name of the query parameter to be used to serve the
|
||||
`XRDS document
|
||||
<http://openid.net/specs/openid-authentication-2_0-12.html#XRDS_Sample>`_.
|
||||
|
||||
:param list sreg:
|
||||
List of strings of optional
|
||||
`SREG
|
||||
<http://openid.net/specs/openid-simple-registration-extension-1_0.html>`_
|
||||
fields.
|
||||
Default = :attr:`OpenID.SREG`.
|
||||
|
||||
:param list sreg_required:
|
||||
List of strings of required
|
||||
`SREG
|
||||
<http://openid.net/specs/openid-simple-registration-extension-1_0.html>`_
|
||||
fields.
|
||||
Default = ``[]``.
|
||||
|
||||
:param list ax:
|
||||
List of strings of optional
|
||||
`AX
|
||||
<http://openid.net/specs/openid-attribute-exchange-1_0.html>`_
|
||||
schemas.
|
||||
Default = :attr:`OpenID.AX`.
|
||||
|
||||
:param list ax_required:
|
||||
List of strings of required
|
||||
`AX
|
||||
<http://openid.net/specs/openid-attribute-exchange-1_0.html>`_
|
||||
schemas.
|
||||
Default = :attr:`OpenID.AX_REQUIRED`.
|
||||
|
||||
:param list pape:
|
||||
of requested
|
||||
`PAPE
|
||||
<http://openid.net/specs/openid-provider-authentication-policy-extension-1_0.html>`_
|
||||
policies.
|
||||
Default = :attr:`OpenID.PAPE`.
|
||||
|
||||
As well as those inherited from :class:`.AuthenticationProvider`
|
||||
constructor.
|
||||
|
||||
"""
|
||||
|
||||
super(OpenID, self).__init__(*args, **kwargs)
|
||||
|
||||
# Allow for other openid store implementations.
|
||||
self.store = self._kwarg(
|
||||
kwargs, 'store', SessionOpenIDStore(
|
||||
self.session))
|
||||
|
||||
# Realm
|
||||
self.use_realm = self._kwarg(kwargs, 'use_realm', True)
|
||||
self.realm_body = self._kwarg(kwargs, 'realm_body', '')
|
||||
self.realm_param = self._kwarg(kwargs, 'realm_param', 'realm')
|
||||
self.xrds_param = self._kwarg(kwargs, 'xrds_param', 'xrds')
|
||||
|
||||
# SREG
|
||||
self.sreg = self._kwarg(kwargs, 'sreg', self.SREG)
|
||||
self.sreg_required = self._kwarg(kwargs, 'sreg_required', [])
|
||||
|
||||
# AX
|
||||
self.ax = self._kwarg(kwargs, 'ax', self.AX)
|
||||
self.ax_required = self._kwarg(kwargs, 'ax_required', self.AX_REQUIRED)
|
||||
# add required schemas to schemas if not already there
|
||||
for i in self.ax_required:
|
||||
if i not in self.ax:
|
||||
self.ax.append(i)
|
||||
|
||||
# PAPE
|
||||
self.pape = self._kwarg(kwargs, 'pape', self.PAPE)
|
||||
|
||||
@staticmethod
|
||||
def _x_user_parser(user, data):
|
||||
|
||||
user.first_name = data.get('ax', {}).get(
|
||||
'http://openid.net/schema/namePerson/first')
|
||||
user.last_name = data.get('ax', {}).get(
|
||||
'http://openid.net/schema/namePerson/last')
|
||||
user.id = data.get('guid')
|
||||
user.link = data.get('ax', {}).get(
|
||||
'http://openid.net/schema/contact/web/default')
|
||||
user.picture = data.get('ax', {}).get(
|
||||
'http://openid.net/schema/media/image')
|
||||
user.nickname = data.get('sreg', {}).get('nickname')
|
||||
user.country = data.get('sreg', {}).get('country')
|
||||
user.postal_code = data.get('sreg', {}).get('postcode')
|
||||
|
||||
user.name = data.get('sreg', {}).get('fullname') or \
|
||||
data.get('ax', {}).get('http://axschema.org/namePerson')
|
||||
|
||||
user.gender = data.get('sreg', {}).get('gender') or \
|
||||
data.get('ax', {}).get('http://openid.net/schema/gender')
|
||||
|
||||
user.locale = data.get('sreg', {}).get('language') or \
|
||||
data.get('ax', {}).get('http://openid.net/schema/language/pref')
|
||||
|
||||
user.timezone = data.get('sreg', {}).get('timezone') or \
|
||||
data.get('ax', {}).get('http://openid.net/schema/timezone')
|
||||
|
||||
user.email = data.get('sreg', {}).get('email') or \
|
||||
data.get('ax', {}).get('http://axschema.org/contact/email') or \
|
||||
data.get('ax', {}).get('http://schema.openid.net/contact/email')
|
||||
|
||||
if data.get('sreg', {}).get('dob'):
|
||||
user.birth_date = datetime.datetime.strptime(
|
||||
data.get('sreg', {}).get('dob'),
|
||||
'%Y-%m-%d'
|
||||
)
|
||||
else:
|
||||
user.birth_date = None
|
||||
|
||||
return user
|
||||
|
||||
@providers.login_decorator
|
||||
def login(self):
|
||||
# Instantiate consumer
|
||||
self.store._log = self._log
|
||||
oi_consumer = consumer.Consumer(self.session, self.store)
|
||||
|
||||
# handle realm and XRDS if there is only one query parameter
|
||||
if self.use_realm and len(self.params) == 1:
|
||||
realm_request = self.params.get(self.realm_param)
|
||||
xrds_request = self.params.get(self.xrds_param)
|
||||
else:
|
||||
realm_request = None
|
||||
xrds_request = None
|
||||
|
||||
# determine type of request
|
||||
if realm_request:
|
||||
# =================================================================
|
||||
# Realm HTML
|
||||
# =================================================================
|
||||
|
||||
self._log(
|
||||
logging.INFO,
|
||||
u'Writing OpenID realm HTML to the response.')
|
||||
xrds_location = '{u}?{x}={x}'.format(u=self.url, x=self.xrds_param)
|
||||
self.write(
|
||||
REALM_HTML.format(
|
||||
xrds_location=xrds_location,
|
||||
body=self.realm_body))
|
||||
|
||||
elif xrds_request:
|
||||
# =================================================================
|
||||
# XRDS XML
|
||||
# =================================================================
|
||||
|
||||
self._log(
|
||||
logging.INFO,
|
||||
u'Writing XRDS XML document to the response.')
|
||||
self.set_header('Content-Type', 'application/xrds+xml')
|
||||
self.write(XRDS_XML.format(return_to=self.url))
|
||||
|
||||
elif self.params.get('openid.mode'):
|
||||
# =================================================================
|
||||
# Phase 2 after redirect
|
||||
# =================================================================
|
||||
|
||||
self._log(
|
||||
logging.INFO,
|
||||
u'Continuing OpenID authentication procedure after redirect.')
|
||||
|
||||
# complete the authentication process
|
||||
response = oi_consumer.complete(self.params, self.url)
|
||||
|
||||
# on success
|
||||
if response.status == consumer.SUCCESS:
|
||||
|
||||
data = {}
|
||||
|
||||
# get user ID
|
||||
data['guid'] = response.getDisplayIdentifier()
|
||||
|
||||
self._log(logging.INFO, u'Authentication successful.')
|
||||
|
||||
# get user data from AX response
|
||||
ax_response = ax.FetchResponse.fromSuccessResponse(response)
|
||||
if ax_response and ax_response.data:
|
||||
self._log(logging.INFO, u'Got AX data.')
|
||||
ax_data = {}
|
||||
# convert iterable values to their first item
|
||||
for k, v in ax_response.data.items():
|
||||
if v and isinstance(v, (list, tuple)):
|
||||
ax_data[k] = v[0]
|
||||
data['ax'] = ax_data
|
||||
|
||||
# get user data from SREG response
|
||||
sreg_response = sreg.SRegResponse.fromSuccessResponse(response)
|
||||
if sreg_response and sreg_response.data:
|
||||
self._log(logging.INFO, u'Got SREG data.')
|
||||
data['sreg'] = sreg_response.data
|
||||
|
||||
# get data from PAPE response
|
||||
pape_response = pape.Response.fromSuccessResponse(response)
|
||||
if pape_response and pape_response.auth_policies:
|
||||
self._log(logging.INFO, u'Got PAPE data.')
|
||||
data['pape'] = pape_response.auth_policies
|
||||
|
||||
# create user
|
||||
self._update_or_create_user(data)
|
||||
|
||||
# =============================================================
|
||||
# We're done!
|
||||
# =============================================================
|
||||
|
||||
elif response.status == consumer.CANCEL:
|
||||
raise CancellationError(
|
||||
u'User cancelled the verification of ID "{0}"!'.format(
|
||||
response.getDisplayIdentifier()))
|
||||
|
||||
elif response.status == consumer.FAILURE:
|
||||
raise FailureError(response.message)
|
||||
|
||||
elif self.identifier: # As set in AuthenticationProvider.__init__
|
||||
# =================================================================
|
||||
# Phase 1 before redirect
|
||||
# =================================================================
|
||||
|
||||
self._log(
|
||||
logging.INFO,
|
||||
u'Starting OpenID authentication procedure.')
|
||||
|
||||
# get AuthRequest object
|
||||
try:
|
||||
auth_request = oi_consumer.begin(self.identifier)
|
||||
except consumer.DiscoveryFailure as e:
|
||||
raise FailureError(
|
||||
u'Discovery failed for identifier {0}!'.format(
|
||||
self.identifier
|
||||
),
|
||||
url=self.identifier,
|
||||
original_message=e.message)
|
||||
|
||||
self._log(
|
||||
logging.INFO,
|
||||
u'Service discovery for identifier {0} successful.'.format(
|
||||
self.identifier))
|
||||
|
||||
# add SREG extension
|
||||
# we need to remove required fields from optional fields because
|
||||
# addExtension then raises an error
|
||||
self.sreg = [i for i in self.sreg if i not in self.sreg_required]
|
||||
auth_request.addExtension(
|
||||
sreg.SRegRequest(
|
||||
optional=self.sreg,
|
||||
required=self.sreg_required)
|
||||
)
|
||||
|
||||
# add AX extension
|
||||
ax_request = ax.FetchRequest()
|
||||
# set AX schemas
|
||||
for i in self.ax:
|
||||
required = i in self.ax_required
|
||||
ax_request.add(ax.AttrInfo(i, required=required))
|
||||
auth_request.addExtension(ax_request)
|
||||
|
||||
# add PAPE extension
|
||||
auth_request.addExtension(pape.Request(self.pape))
|
||||
|
||||
# prepare realm and return_to URLs
|
||||
if self.use_realm:
|
||||
realm = return_to = '{u}?{r}={r}'.format(
|
||||
u=self.url, r=self.realm_param)
|
||||
else:
|
||||
realm = return_to = self.url
|
||||
|
||||
url = auth_request.redirectURL(realm, return_to)
|
||||
|
||||
if auth_request.shouldSendRedirect():
|
||||
# can be redirected
|
||||
url = auth_request.redirectURL(realm, return_to)
|
||||
self._log(
|
||||
logging.INFO,
|
||||
u'Redirecting user to {0}.'.format(url))
|
||||
self.redirect(url)
|
||||
else:
|
||||
# must be sent as POST
|
||||
# this writes a html post form with auto-submit
|
||||
self._log(
|
||||
logging.INFO,
|
||||
u'Writing an auto-submit HTML form to the response.')
|
||||
form = auth_request.htmlMarkup(
|
||||
realm, return_to, False, dict(
|
||||
id='openid_form'))
|
||||
self.write(form)
|
||||
else:
|
||||
raise OpenIDError('No identifier specified!')
|
||||
|
||||
|
||||
class Yahoo(OpenID):
|
||||
"""
|
||||
Yahoo :class:`.OpenID` provider with the :attr:`.identifier` predefined to
|
||||
``"me.yahoo.com"``.
|
||||
"""
|
||||
|
||||
identifier = 'me.yahoo.com'
|
||||
|
||||
|
||||
class Google(OpenID):
|
||||
"""
|
||||
Google :class:`.OpenID` provider with the :attr:`.identifier` predefined to
|
||||
``"https://www.google.com/accounts/o8/id"``.
|
||||
"""
|
||||
|
||||
identifier = 'https://www.google.com/accounts/o8/id'
|
||||
6
rhodecode/lib/_vendor/authomatic/providers/persona.py
Executable file
6
rhodecode/lib/_vendor/authomatic/providers/persona.py
Executable file
|
|
@ -0,0 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from authomatic import providers
|
||||
|
||||
|
||||
class MozillaPersona(providers.AuthenticationProvider):
|
||||
pass
|
||||
839
rhodecode/lib/_vendor/authomatic/six.py
Executable file
839
rhodecode/lib/_vendor/authomatic/six.py
Executable file
|
|
@ -0,0 +1,839 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Utilities for writing code that runs on Python 2 and 3"""
|
||||
|
||||
# Copyright (c) 2010-2015 Benjamin Peterson
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import functools
|
||||
import itertools
|
||||
import operator
|
||||
import sys
|
||||
import types
|
||||
|
||||
__author__ = "Benjamin Peterson <benjamin@python.org>"
|
||||
__version__ = "1.9.0"
|
||||
|
||||
|
||||
# Useful for very coarse version differentiation.
|
||||
PY2 = sys.version_info[0] == 2
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
if PY3:
|
||||
string_types = str,
|
||||
integer_types = int,
|
||||
class_types = type,
|
||||
text_type = str
|
||||
binary_type = bytes
|
||||
|
||||
MAXSIZE = sys.maxsize
|
||||
else:
|
||||
string_types = basestring,
|
||||
integer_types = (int, long)
|
||||
class_types = (type, types.ClassType)
|
||||
text_type = unicode
|
||||
binary_type = str
|
||||
|
||||
if sys.platform.startswith("java"):
|
||||
# Jython always uses 32 bits.
|
||||
MAXSIZE = int((1 << 31) - 1)
|
||||
else:
|
||||
# It's possible to have sizeof(long) != sizeof(Py_ssize_t).
|
||||
class X(object):
|
||||
def __len__(self):
|
||||
return 1 << 31
|
||||
try:
|
||||
len(X())
|
||||
except OverflowError:
|
||||
# 32-bit
|
||||
MAXSIZE = int((1 << 31) - 1)
|
||||
else:
|
||||
# 64-bit
|
||||
MAXSIZE = int((1 << 63) - 1)
|
||||
del X
|
||||
|
||||
|
||||
def _add_doc(func, doc):
|
||||
"""Add documentation to a function."""
|
||||
func.__doc__ = doc
|
||||
|
||||
|
||||
def _import_module(name):
|
||||
"""Import module, returning the module after the last dot."""
|
||||
__import__(name)
|
||||
return sys.modules[name]
|
||||
|
||||
|
||||
class _LazyDescr(object):
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def __get__(self, obj, tp):
|
||||
result = self._resolve()
|
||||
setattr(obj, self.name, result) # Invokes __set__.
|
||||
try:
|
||||
# This is a bit ugly, but it avoids running this again by
|
||||
# removing this descriptor.
|
||||
delattr(obj.__class__, self.name)
|
||||
except AttributeError:
|
||||
pass
|
||||
return result
|
||||
|
||||
|
||||
class MovedModule(_LazyDescr):
|
||||
|
||||
def __init__(self, name, old, new=None):
|
||||
super(MovedModule, self).__init__(name)
|
||||
if PY3:
|
||||
if new is None:
|
||||
new = name
|
||||
self.mod = new
|
||||
else:
|
||||
self.mod = old
|
||||
|
||||
def _resolve(self):
|
||||
return _import_module(self.mod)
|
||||
|
||||
def __getattr__(self, attr):
|
||||
_module = self._resolve()
|
||||
value = getattr(_module, attr)
|
||||
setattr(self, attr, value)
|
||||
return value
|
||||
|
||||
|
||||
class _LazyModule(types.ModuleType):
|
||||
|
||||
def __init__(self, name):
|
||||
super(_LazyModule, self).__init__(name)
|
||||
self.__doc__ = self.__class__.__doc__
|
||||
|
||||
def __dir__(self):
|
||||
attrs = ["__doc__", "__name__"]
|
||||
attrs += [attr.name for attr in self._moved_attributes]
|
||||
return attrs
|
||||
|
||||
# Subclasses should override this
|
||||
_moved_attributes = []
|
||||
|
||||
|
||||
class MovedAttribute(_LazyDescr):
|
||||
|
||||
def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
|
||||
super(MovedAttribute, self).__init__(name)
|
||||
if PY3:
|
||||
if new_mod is None:
|
||||
new_mod = name
|
||||
self.mod = new_mod
|
||||
if new_attr is None:
|
||||
if old_attr is None:
|
||||
new_attr = name
|
||||
else:
|
||||
new_attr = old_attr
|
||||
self.attr = new_attr
|
||||
else:
|
||||
self.mod = old_mod
|
||||
if old_attr is None:
|
||||
old_attr = name
|
||||
self.attr = old_attr
|
||||
|
||||
def _resolve(self):
|
||||
module = _import_module(self.mod)
|
||||
return getattr(module, self.attr)
|
||||
|
||||
|
||||
class _SixMetaPathImporter(object):
|
||||
"""
|
||||
A meta path importer to import six.moves and its submodules.
|
||||
|
||||
This class implements a PEP302 finder and loader. It should be compatible
|
||||
with Python 2.5 and all existing versions of Python3
|
||||
"""
|
||||
def __init__(self, six_module_name):
|
||||
self.name = six_module_name
|
||||
self.known_modules = {}
|
||||
|
||||
def _add_module(self, mod, *fullnames):
|
||||
for fullname in fullnames:
|
||||
self.known_modules[self.name + "." + fullname] = mod
|
||||
|
||||
def _get_module(self, fullname):
|
||||
return self.known_modules[self.name + "." + fullname]
|
||||
|
||||
def find_module(self, fullname, path=None):
|
||||
if fullname in self.known_modules:
|
||||
return self
|
||||
return None
|
||||
|
||||
def __get_module(self, fullname):
|
||||
try:
|
||||
return self.known_modules[fullname]
|
||||
except KeyError:
|
||||
raise ImportError("This loader does not know module " + fullname)
|
||||
|
||||
def load_module(self, fullname):
|
||||
try:
|
||||
# in case of a reload
|
||||
return sys.modules[fullname]
|
||||
except KeyError:
|
||||
pass
|
||||
mod = self.__get_module(fullname)
|
||||
if isinstance(mod, MovedModule):
|
||||
mod = mod._resolve()
|
||||
else:
|
||||
mod.__loader__ = self
|
||||
sys.modules[fullname] = mod
|
||||
return mod
|
||||
|
||||
def is_package(self, fullname):
|
||||
"""
|
||||
Return true, if the named module is a package.
|
||||
|
||||
We need this method to get correct spec objects with
|
||||
Python 3.4 (see PEP451)
|
||||
"""
|
||||
return hasattr(self.__get_module(fullname), "__path__")
|
||||
|
||||
def get_code(self, fullname):
|
||||
"""Return None
|
||||
|
||||
Required, if is_package is implemented"""
|
||||
self.__get_module(fullname) # eventually raises ImportError
|
||||
return None
|
||||
get_source = get_code # same as get_code
|
||||
|
||||
_importer = _SixMetaPathImporter(__name__)
|
||||
|
||||
|
||||
class _MovedItems(_LazyModule):
|
||||
"""Lazy loading of moved objects"""
|
||||
__path__ = [] # mark as package
|
||||
|
||||
|
||||
_moved_attributes = [
|
||||
MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
|
||||
MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
|
||||
MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
|
||||
MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
|
||||
MovedAttribute("intern", "__builtin__", "sys"),
|
||||
MovedAttribute("map", "itertools", "builtins", "imap", "map"),
|
||||
MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
|
||||
MovedAttribute("reload_module", "__builtin__", "imp", "reload"),
|
||||
MovedAttribute("reduce", "__builtin__", "functools"),
|
||||
MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
|
||||
MovedAttribute("StringIO", "StringIO", "io"),
|
||||
MovedAttribute("UserDict", "UserDict", "collections"),
|
||||
MovedAttribute("UserList", "UserList", "collections"),
|
||||
MovedAttribute("UserString", "UserString", "collections"),
|
||||
MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
|
||||
MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
|
||||
MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
|
||||
|
||||
MovedModule("builtins", "__builtin__"),
|
||||
MovedModule("configparser", "ConfigParser"),
|
||||
MovedModule("copyreg", "copy_reg"),
|
||||
MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
|
||||
MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"),
|
||||
MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
|
||||
MovedModule("http_cookies", "Cookie", "http.cookies"),
|
||||
MovedModule("html_entities", "htmlentitydefs", "html.entities"),
|
||||
MovedModule("html_parser", "HTMLParser", "html.parser"),
|
||||
MovedModule("http_client", "httplib", "http.client"),
|
||||
MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
|
||||
MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"),
|
||||
MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
|
||||
MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
|
||||
MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
|
||||
MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
|
||||
MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
|
||||
MovedModule("cPickle", "cPickle", "pickle"),
|
||||
MovedModule("queue", "Queue"),
|
||||
MovedModule("reprlib", "repr"),
|
||||
MovedModule("socketserver", "SocketServer"),
|
||||
MovedModule("_thread", "thread", "_thread"),
|
||||
MovedModule("tkinter", "Tkinter"),
|
||||
MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
|
||||
MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
|
||||
MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
|
||||
MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
|
||||
MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
|
||||
MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
|
||||
MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
|
||||
MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
|
||||
MovedModule("tkinter_colorchooser", "tkColorChooser",
|
||||
"tkinter.colorchooser"),
|
||||
MovedModule("tkinter_commondialog", "tkCommonDialog",
|
||||
"tkinter.commondialog"),
|
||||
MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
|
||||
MovedModule("tkinter_font", "tkFont", "tkinter.font"),
|
||||
MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
|
||||
MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
|
||||
"tkinter.simpledialog"),
|
||||
MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
|
||||
MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
|
||||
MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
|
||||
MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
|
||||
MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
|
||||
MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
|
||||
MovedModule("winreg", "_winreg"),
|
||||
]
|
||||
for attr in _moved_attributes:
|
||||
setattr(_MovedItems, attr.name, attr)
|
||||
if isinstance(attr, MovedModule):
|
||||
_importer._add_module(attr, "moves." + attr.name)
|
||||
del attr
|
||||
|
||||
_MovedItems._moved_attributes = _moved_attributes
|
||||
|
||||
moves = _MovedItems(__name__ + ".moves")
|
||||
_importer._add_module(moves, "moves")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_parse(_LazyModule):
|
||||
"""Lazy loading of moved objects in six.moves.urllib_parse"""
|
||||
|
||||
|
||||
_urllib_parse_moved_attributes = [
|
||||
MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urljoin", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urlparse", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("quote", "urllib", "urllib.parse"),
|
||||
MovedAttribute("quote_plus", "urllib", "urllib.parse"),
|
||||
MovedAttribute("unquote", "urllib", "urllib.parse"),
|
||||
MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
|
||||
MovedAttribute("urlencode", "urllib", "urllib.parse"),
|
||||
MovedAttribute("splitquery", "urllib", "urllib.parse"),
|
||||
MovedAttribute("splittag", "urllib", "urllib.parse"),
|
||||
MovedAttribute("splituser", "urllib", "urllib.parse"),
|
||||
MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("uses_params", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("uses_query", "urlparse", "urllib.parse"),
|
||||
MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
|
||||
]
|
||||
for attr in _urllib_parse_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_parse, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
|
||||
"moves.urllib_parse", "moves.urllib.parse")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_error(_LazyModule):
|
||||
"""Lazy loading of moved objects in six.moves.urllib_error"""
|
||||
|
||||
|
||||
_urllib_error_moved_attributes = [
|
||||
MovedAttribute("URLError", "urllib2", "urllib.error"),
|
||||
MovedAttribute("HTTPError", "urllib2", "urllib.error"),
|
||||
MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
|
||||
]
|
||||
for attr in _urllib_error_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_error, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
|
||||
"moves.urllib_error", "moves.urllib.error")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_request(_LazyModule):
|
||||
"""Lazy loading of moved objects in six.moves.urllib_request"""
|
||||
|
||||
|
||||
_urllib_request_moved_attributes = [
|
||||
MovedAttribute("urlopen", "urllib2", "urllib.request"),
|
||||
MovedAttribute("install_opener", "urllib2", "urllib.request"),
|
||||
MovedAttribute("build_opener", "urllib2", "urllib.request"),
|
||||
MovedAttribute("pathname2url", "urllib", "urllib.request"),
|
||||
MovedAttribute("url2pathname", "urllib", "urllib.request"),
|
||||
MovedAttribute("getproxies", "urllib", "urllib.request"),
|
||||
MovedAttribute("Request", "urllib2", "urllib.request"),
|
||||
MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
|
||||
MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
|
||||
MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("FileHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
|
||||
MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
|
||||
MovedAttribute("urlretrieve", "urllib", "urllib.request"),
|
||||
MovedAttribute("urlcleanup", "urllib", "urllib.request"),
|
||||
MovedAttribute("URLopener", "urllib", "urllib.request"),
|
||||
MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
|
||||
MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
|
||||
]
|
||||
for attr in _urllib_request_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_request, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
|
||||
"moves.urllib_request", "moves.urllib.request")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_response(_LazyModule):
|
||||
"""Lazy loading of moved objects in six.moves.urllib_response"""
|
||||
|
||||
|
||||
_urllib_response_moved_attributes = [
|
||||
MovedAttribute("addbase", "urllib", "urllib.response"),
|
||||
MovedAttribute("addclosehook", "urllib", "urllib.response"),
|
||||
MovedAttribute("addinfo", "urllib", "urllib.response"),
|
||||
MovedAttribute("addinfourl", "urllib", "urllib.response"),
|
||||
]
|
||||
for attr in _urllib_response_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_response, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
|
||||
"moves.urllib_response", "moves.urllib.response")
|
||||
|
||||
|
||||
class Module_six_moves_urllib_robotparser(_LazyModule):
|
||||
"""Lazy loading of moved objects in six.moves.urllib_robotparser"""
|
||||
|
||||
|
||||
_urllib_robotparser_moved_attributes = [
|
||||
MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
|
||||
]
|
||||
for attr in _urllib_robotparser_moved_attributes:
|
||||
setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
|
||||
del attr
|
||||
|
||||
Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
|
||||
"moves.urllib_robotparser", "moves.urllib.robotparser")
|
||||
|
||||
|
||||
class Module_six_moves_urllib(types.ModuleType):
|
||||
"""Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
|
||||
__path__ = [] # mark as package
|
||||
parse = _importer._get_module("moves.urllib_parse")
|
||||
error = _importer._get_module("moves.urllib_error")
|
||||
request = _importer._get_module("moves.urllib_request")
|
||||
response = _importer._get_module("moves.urllib_response")
|
||||
robotparser = _importer._get_module("moves.urllib_robotparser")
|
||||
|
||||
def __dir__(self):
|
||||
return ['parse', 'error', 'request', 'response', 'robotparser']
|
||||
|
||||
_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
|
||||
"moves.urllib")
|
||||
|
||||
|
||||
def add_move(move):
|
||||
"""Add an item to six.moves."""
|
||||
setattr(_MovedItems, move.name, move)
|
||||
|
||||
|
||||
def remove_move(name):
|
||||
"""Remove item from six.moves."""
|
||||
try:
|
||||
delattr(_MovedItems, name)
|
||||
except AttributeError:
|
||||
try:
|
||||
del moves.__dict__[name]
|
||||
except KeyError:
|
||||
raise AttributeError("no such move, %r" % (name,))
|
||||
|
||||
|
||||
if PY3:
|
||||
_meth_func = "__func__"
|
||||
_meth_self = "__self__"
|
||||
|
||||
_func_closure = "__closure__"
|
||||
_func_code = "__code__"
|
||||
_func_defaults = "__defaults__"
|
||||
_func_globals = "__globals__"
|
||||
else:
|
||||
_meth_func = "im_func"
|
||||
_meth_self = "im_self"
|
||||
|
||||
_func_closure = "func_closure"
|
||||
_func_code = "func_code"
|
||||
_func_defaults = "func_defaults"
|
||||
_func_globals = "func_globals"
|
||||
|
||||
|
||||
try:
|
||||
advance_iterator = next
|
||||
except NameError:
|
||||
def advance_iterator(it):
|
||||
return it.next()
|
||||
next = advance_iterator
|
||||
|
||||
|
||||
try:
|
||||
callable = callable
|
||||
except NameError:
|
||||
def callable(obj):
|
||||
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
|
||||
|
||||
|
||||
if PY3:
|
||||
def get_unbound_function(unbound):
|
||||
return unbound
|
||||
|
||||
create_bound_method = types.MethodType
|
||||
|
||||
Iterator = object
|
||||
else:
|
||||
def get_unbound_function(unbound):
|
||||
return unbound.im_func
|
||||
|
||||
def create_bound_method(func, obj):
|
||||
return types.MethodType(func, obj, obj.__class__)
|
||||
|
||||
class Iterator(object):
|
||||
|
||||
def next(self):
|
||||
return type(self).__next__(self)
|
||||
|
||||
callable = callable
|
||||
_add_doc(get_unbound_function,
|
||||
"""Get the function out of a possibly unbound function""")
|
||||
|
||||
|
||||
get_method_function = operator.attrgetter(_meth_func)
|
||||
get_method_self = operator.attrgetter(_meth_self)
|
||||
get_function_closure = operator.attrgetter(_func_closure)
|
||||
get_function_code = operator.attrgetter(_func_code)
|
||||
get_function_defaults = operator.attrgetter(_func_defaults)
|
||||
get_function_globals = operator.attrgetter(_func_globals)
|
||||
|
||||
|
||||
if PY3:
|
||||
def iterkeys(d, **kw):
|
||||
return iter(d.keys(**kw))
|
||||
|
||||
def itervalues(d, **kw):
|
||||
return iter(d.values(**kw))
|
||||
|
||||
def iteritems(d, **kw):
|
||||
return iter(d.items(**kw))
|
||||
|
||||
def iterlists(d, **kw):
|
||||
return iter(d.lists(**kw))
|
||||
|
||||
viewkeys = operator.methodcaller("keys")
|
||||
|
||||
viewvalues = operator.methodcaller("values")
|
||||
|
||||
viewitems = operator.methodcaller("items")
|
||||
else:
|
||||
def iterkeys(d, **kw):
|
||||
return iter(d.iterkeys(**kw))
|
||||
|
||||
def itervalues(d, **kw):
|
||||
return iter(d.itervalues(**kw))
|
||||
|
||||
def iteritems(d, **kw):
|
||||
return iter(d.iteritems(**kw))
|
||||
|
||||
def iterlists(d, **kw):
|
||||
return iter(d.iterlists(**kw))
|
||||
|
||||
viewkeys = operator.methodcaller("viewkeys")
|
||||
|
||||
viewvalues = operator.methodcaller("viewvalues")
|
||||
|
||||
viewitems = operator.methodcaller("viewitems")
|
||||
|
||||
_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
|
||||
_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
|
||||
_add_doc(iteritems,
|
||||
"Return an iterator over the (key, value) pairs of a dictionary.")
|
||||
_add_doc(iterlists,
|
||||
"Return an iterator over the (key, [values]) pairs of a dictionary.")
|
||||
|
||||
|
||||
if PY3:
|
||||
def b(s):
|
||||
return s.encode("latin-1")
|
||||
def u(s):
|
||||
return s
|
||||
unichr = chr
|
||||
if sys.version_info[1] <= 1:
|
||||
def int2byte(i):
|
||||
return bytes((i,))
|
||||
else:
|
||||
# This is about 2x faster than the implementation above on 3.2+
|
||||
int2byte = operator.methodcaller("to_bytes", 1, "big")
|
||||
byte2int = operator.itemgetter(0)
|
||||
indexbytes = operator.getitem
|
||||
iterbytes = iter
|
||||
import io
|
||||
StringIO = io.StringIO
|
||||
BytesIO = io.BytesIO
|
||||
_assertCountEqual = "assertCountEqual"
|
||||
_assertRaisesRegex = "assertRaisesRegex"
|
||||
_assertRegex = "assertRegex"
|
||||
else:
|
||||
def b(s):
|
||||
return s
|
||||
# Workaround for standalone backslash
|
||||
def u(s):
|
||||
return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
|
||||
unichr = unichr
|
||||
int2byte = chr
|
||||
def byte2int(bs):
|
||||
return ord(bs[0])
|
||||
def indexbytes(buf, i):
|
||||
return ord(buf[i])
|
||||
iterbytes = functools.partial(itertools.imap, ord)
|
||||
import StringIO
|
||||
StringIO = BytesIO = StringIO.StringIO
|
||||
_assertCountEqual = "assertItemsEqual"
|
||||
_assertRaisesRegex = "assertRaisesRegexp"
|
||||
_assertRegex = "assertRegexpMatches"
|
||||
_add_doc(b, """Byte literal""")
|
||||
_add_doc(u, """Text literal""")
|
||||
|
||||
|
||||
def assertCountEqual(self, *args, **kwargs):
|
||||
return getattr(self, _assertCountEqual)(*args, **kwargs)
|
||||
|
||||
|
||||
def assertRaisesRegex(self, *args, **kwargs):
|
||||
return getattr(self, _assertRaisesRegex)(*args, **kwargs)
|
||||
|
||||
|
||||
def assertRegex(self, *args, **kwargs):
|
||||
return getattr(self, _assertRegex)(*args, **kwargs)
|
||||
|
||||
|
||||
if PY3:
|
||||
exec_ = getattr(moves.builtins, "exec")
|
||||
|
||||
|
||||
def reraise(tp, value, tb=None):
|
||||
if value is None:
|
||||
value = tp()
|
||||
if value.__traceback__ is not tb:
|
||||
raise value.with_traceback(tb)
|
||||
raise value
|
||||
|
||||
else:
|
||||
def exec_(_code_, _globs_=None, _locs_=None):
|
||||
"""Execute code in a namespace."""
|
||||
if _globs_ is None:
|
||||
frame = sys._getframe(1)
|
||||
_globs_ = frame.f_globals
|
||||
if _locs_ is None:
|
||||
_locs_ = frame.f_locals
|
||||
del frame
|
||||
elif _locs_ is None:
|
||||
_locs_ = _globs_
|
||||
exec("""exec _code_ in _globs_, _locs_""")
|
||||
|
||||
|
||||
exec_("""def reraise(tp, value, tb=None):
|
||||
raise tp, value, tb
|
||||
""")
|
||||
|
||||
|
||||
if sys.version_info[:2] == (3, 2):
|
||||
exec_("""def raise_from(value, from_value):
|
||||
if from_value is None:
|
||||
raise value
|
||||
raise value from from_value
|
||||
""")
|
||||
elif sys.version_info[:2] > (3, 2):
|
||||
exec_("""def raise_from(value, from_value):
|
||||
raise value from from_value
|
||||
""")
|
||||
else:
|
||||
def raise_from(value, from_value):
|
||||
raise value
|
||||
|
||||
|
||||
print_ = getattr(moves.builtins, "print", None)
|
||||
if print_ is None:
|
||||
def print_(*args, **kwargs):
|
||||
"""The new-style print function for Python 2.4 and 2.5."""
|
||||
fp = kwargs.pop("file", sys.stdout)
|
||||
if fp is None:
|
||||
return
|
||||
def write(data):
|
||||
if not isinstance(data, basestring):
|
||||
data = str(data)
|
||||
# If the file has an encoding, encode unicode with it.
|
||||
if (isinstance(fp, file) and
|
||||
isinstance(data, unicode) and
|
||||
fp.encoding is not None):
|
||||
errors = getattr(fp, "errors", None)
|
||||
if errors is None:
|
||||
errors = "strict"
|
||||
data = data.encode(fp.encoding, errors)
|
||||
fp.write(data)
|
||||
want_unicode = False
|
||||
sep = kwargs.pop("sep", None)
|
||||
if sep is not None:
|
||||
if isinstance(sep, unicode):
|
||||
want_unicode = True
|
||||
elif not isinstance(sep, str):
|
||||
raise TypeError("sep must be None or a string")
|
||||
end = kwargs.pop("end", None)
|
||||
if end is not None:
|
||||
if isinstance(end, unicode):
|
||||
want_unicode = True
|
||||
elif not isinstance(end, str):
|
||||
raise TypeError("end must be None or a string")
|
||||
if kwargs:
|
||||
raise TypeError("invalid keyword arguments to print()")
|
||||
if not want_unicode:
|
||||
for arg in args:
|
||||
if isinstance(arg, unicode):
|
||||
want_unicode = True
|
||||
break
|
||||
if want_unicode:
|
||||
newline = unicode("\n")
|
||||
space = unicode(" ")
|
||||
else:
|
||||
newline = "\n"
|
||||
space = " "
|
||||
if sep is None:
|
||||
sep = space
|
||||
if end is None:
|
||||
end = newline
|
||||
for i, arg in enumerate(args):
|
||||
if i:
|
||||
write(sep)
|
||||
write(arg)
|
||||
write(end)
|
||||
if sys.version_info[:2] < (3, 3):
|
||||
_print = print_
|
||||
def print_(*args, **kwargs):
|
||||
fp = kwargs.get("file", sys.stdout)
|
||||
flush = kwargs.pop("flush", False)
|
||||
_print(*args, **kwargs)
|
||||
if flush and fp is not None:
|
||||
fp.flush()
|
||||
|
||||
_add_doc(reraise, """Reraise an exception.""")
|
||||
|
||||
if sys.version_info[0:2] < (3, 4):
|
||||
def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
|
||||
updated=functools.WRAPPER_UPDATES):
|
||||
def wrapper(f):
|
||||
f = functools.wraps(wrapped, assigned, updated)(f)
|
||||
f.__wrapped__ = wrapped
|
||||
return f
|
||||
return wrapper
|
||||
else:
|
||||
wraps = functools.wraps
|
||||
|
||||
def with_metaclass(meta, *bases):
|
||||
"""Create a base class with a metaclass."""
|
||||
# This requires a bit of explanation: the basic idea is to make a dummy
|
||||
# metaclass for one level of class instantiation that replaces itself with
|
||||
# the actual metaclass.
|
||||
class metaclass(meta):
|
||||
def __new__(cls, name, this_bases, d):
|
||||
return meta(name, bases, d)
|
||||
return type.__new__(metaclass, 'temporary_class', (), {})
|
||||
|
||||
|
||||
def add_metaclass(metaclass):
|
||||
"""Class decorator for creating a class with a metaclass."""
|
||||
def wrapper(cls):
|
||||
orig_vars = cls.__dict__.copy()
|
||||
slots = orig_vars.get('__slots__')
|
||||
if slots is not None:
|
||||
if isinstance(slots, str):
|
||||
slots = [slots]
|
||||
for slots_var in slots:
|
||||
orig_vars.pop(slots_var)
|
||||
orig_vars.pop('__dict__', None)
|
||||
orig_vars.pop('__weakref__', None)
|
||||
return metaclass(cls.__name__, cls.__bases__, orig_vars)
|
||||
return wrapper
|
||||
|
||||
|
||||
def python_2_unicode_compatible(klass):
|
||||
"""
|
||||
A decorator that defines __unicode__ and __str__ methods under Python 2.
|
||||
Under Python 3 it does nothing.
|
||||
|
||||
To support Python 2 and 3 with a single code base, define a __str__ method
|
||||
returning text and apply this decorator to the class.
|
||||
"""
|
||||
if PY2:
|
||||
if '__str__' not in klass.__dict__:
|
||||
raise ValueError("@python_2_unicode_compatible cannot be applied "
|
||||
"to %s because it doesn't define __str__()." %
|
||||
klass.__name__)
|
||||
klass.__unicode__ = klass.__str__
|
||||
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
|
||||
return klass
|
||||
|
||||
|
||||
# Complete the moves implementation.
|
||||
# This code is at the end of this module to speed up module loading.
|
||||
# Turn this module into a package.
|
||||
__path__ = [] # required for PEP 302 and PEP 451
|
||||
__package__ = __name__ # see PEP 366 @ReservedAssignment
|
||||
if globals().get("__spec__") is not None:
|
||||
__spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable
|
||||
# Remove other six meta path importers, since they cause problems. This can
|
||||
# happen if six is removed from sys.modules and then reloaded. (Setuptools does
|
||||
# this for some reason.)
|
||||
if sys.meta_path:
|
||||
for i, importer in enumerate(sys.meta_path):
|
||||
# Here's some real nastiness: Another "instance" of the six module might
|
||||
# be floating around. Therefore, we can't use isinstance() to check for
|
||||
# the six meta path importer, since the other six instance will have
|
||||
# inserted an importer with different class.
|
||||
if (type(importer).__name__ == "_SixMetaPathImporter" and
|
||||
importer.name == __name__):
|
||||
del sys.meta_path[i]
|
||||
break
|
||||
del i, importer
|
||||
# Finally, add the importer to the meta path import hook.
|
||||
sys.meta_path.append(_importer)
|
||||
Loading…
Add table
Add a link
Reference in a new issue