From 21e577ba25784b3f7eadfe407e7f36c48b7cce95 Mon Sep 17 00:00:00 2001
From: Alexandre Ferland <alf@pixmob.com>
Date: Sun, 5 Jun 2016 00:27:39 -0400
Subject: [PATCH] add python3 support

---
 .travis.yml                                  |  4 +++-
 README.md                                    | 18 +++++++++++++-----
 dev_requirements.txt                         |  2 +-
 docs/conf.py                                 |  6 +++---
 docs/index.rst                               | 10 +++++++---
 examples/basic_auth/app.py                   |  2 +-
 examples/basic_auth/app_oldap.py             |  2 +-
 examples/blueprints/blueprints/extensions.py |  2 +-
 examples/groups/app.py                       |  2 +-
 examples/groups/app_oldap.py                 |  2 +-
 flask_simpleldap/__init__.py                 | 20 +++++++++-----------
 requirements.txt                             |  4 ++--
 setup.py                                     |  9 +++++----
 13 files changed, 48 insertions(+), 35 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index a935737..951eaf4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,8 +1,10 @@
 language: python
 python:
-  - "2.6"
   - "2.7"
+  - "3.4"
+  - "3.5"
 env:
+  - FLASK=0.11
   - FLASK=0.10.1
   - FLASK=0.9
 install:
diff --git a/README.md b/README.md
index d36f6f2..c375b2a 100644
--- a/README.md
+++ b/README.md
@@ -13,15 +13,15 @@ First, install Flask-SimpleLDAP:
     $ pip install flask-simpleldap
     
 Flask-SimpleLDAP depends, and will install for you, recent versions of Flask
-(0.9 or later) and python-ldap. Flask-SimpleLDAP is compatible
-with and tested on Python 2.6 and 2.7.
+(0.9 or later) and [pyldap](https://github.com/pyldap/pyldap). Flask-SimpleLDAP is compatible
+with and tested on Python 2.7, 3.4 and 3.5.
 
 Next, add a ``LDAP`` instance to your code and at least the three
 required configuration options:
 
 ```python
 from flask import Flask
-from flask.ext.simpleldap import LDAP
+from flask_simpleldap import LDAP
 
 app = Flask(__name__)
 ldap = LDAP(app)
@@ -46,7 +46,7 @@ and [blueprints](http://flask.pocoo.org/docs/blueprints/).
 
 
 OpenLDAP
-----------
+--------
 
 Add the ``LDAP`` instance to your code and depending on your OpenLDAP
 configuration, add the following at least LDAP_USER_OBJECT_FILTER and 
@@ -54,7 +54,7 @@ LDAP_USER_OBJECT_FILTER.
 
 ```python
 from flask import Flask
-from flask.ext.simpleldap import LDAP
+from flask_simpleldap import LDAP
 
 app = Flask(__name__)
 ldap = LDAP(app)
@@ -84,6 +84,14 @@ def ldap_protected():
 ```
 
 
+Migrating from 0.x to 1.x
+-------------------------
+
+The only major change from 0.x releases and 1.x is the underlying LDAP library changed from python-ldap to
+[pyldap](https://github.com/pyldap/pyldap) which is fork that adds Python 3.x support. Everything else SHOULD
+be the same, but don't hesitate to open an issue if encounter some problem upgrading from 0.x to 1.x.
+
+
 Resources
 ---------
 
diff --git a/dev_requirements.txt b/dev_requirements.txt
index 2707c0f..355d97b 100644
--- a/dev_requirements.txt
+++ b/dev_requirements.txt
@@ -1 +1 @@
-python-ldap==2.4.20
+pyldap==2.4.25.1
diff --git a/docs/conf.py b/docs/conf.py
index 2a46ad6..1c97725 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -56,16 +56,16 @@ master_doc = 'index'
 
 # General information about the project.
 project = u'Flask-SimpleLDAP'
-copyright = u'2015, Alexandre Ferland'
+copyright = u'2016, Alexandre Ferland'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
 # The short X.Y version.
-version = '0.4.0'
+version = '1.0.0'
 # The full version, including alpha/beta/rc tags.
-release = '0.4.0'
+release = '1.0.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/docs/index.rst b/docs/index.rst
index be2aca3..ada76e8 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -19,8 +19,8 @@ First, install Flask-SimpleLDAP:
     $ pip install flask-simpleldap
 
 Flask-SimpleLDAP depends, and will install for you, recent versions of Flask
-(0.9 or later) and python-ldap. Flask-SimpleLDAP is compatible
-with and tested on Python 2.6 and 2.7.
+(0.9 or later) and pyldap. Flask-SimpleLDAP is compatible
+with and tested on Python 2.7, 3.4 and 3.5.
 
 Next, add a :class:`~flask_simpleldap.LDAP` to your code and at least the three
 required configuration options:
@@ -28,7 +28,7 @@ required configuration options:
 .. code-block:: python
 
     from flask import Flask
-    from flask.ext.simpleldap import LDAP
+    from flask_simpleldap import LDAP
 
     app = Flask(__name__)
     ldap = LDAP(app)
@@ -114,6 +114,10 @@ History
 
 Changes:
 
+- 1.0.0 June 4, 2016
+
+  - Python 3.x support. Switched from python-ldap to pyldap which is a fork with Python 3.x support.
+
 - 0.4.0: September 5, 2015
 
   - Added support for OpenLDAP directories. Thanks to `@jm66 <https://github.com/jm66>`_ on GitHub.
diff --git a/examples/basic_auth/app.py b/examples/basic_auth/app.py
index 40c97a9..efe7465 100644
--- a/examples/basic_auth/app.py
+++ b/examples/basic_auth/app.py
@@ -1,5 +1,5 @@
 from flask import Flask, g, request, session, redirect, url_for
-from flask.ext.simpleldap import LDAP
+from flask_simpleldap import LDAP
 
 app = Flask(__name__)
 app.secret_key = 'dev key'
diff --git a/examples/basic_auth/app_oldap.py b/examples/basic_auth/app_oldap.py
index 06880f5..d795e45 100644
--- a/examples/basic_auth/app_oldap.py
+++ b/examples/basic_auth/app_oldap.py
@@ -1,5 +1,5 @@
 from flask import Flask, g, request, session, redirect, url_for
-from flask.ext.simpleldap import LDAP
+from flask_simpleldap import LDAP
 
 app = Flask(__name__)
 app.secret_key = 'dev key'
diff --git a/examples/blueprints/blueprints/extensions.py b/examples/blueprints/blueprints/extensions.py
index cd5765e..9549889 100644
--- a/examples/blueprints/blueprints/extensions.py
+++ b/examples/blueprints/blueprints/extensions.py
@@ -1,2 +1,2 @@
-from flask.ext.simpleldap import LDAP
+from flask_simpleldap import LDAP
 ldap = LDAP()
diff --git a/examples/groups/app.py b/examples/groups/app.py
index 88b697c..61e74b5 100644
--- a/examples/groups/app.py
+++ b/examples/groups/app.py
@@ -1,5 +1,5 @@
 from flask import Flask, g, request, session, redirect, url_for
-from flask.ext.simpleldap import LDAP
+from flask_simpleldap import LDAP
 
 app = Flask(__name__)
 app.secret_key = 'dev key'
diff --git a/examples/groups/app_oldap.py b/examples/groups/app_oldap.py
index 98af66e..c4de23c 100644
--- a/examples/groups/app_oldap.py
+++ b/examples/groups/app_oldap.py
@@ -1,5 +1,5 @@
 from flask import Flask, g, request, session, redirect, url_for
-from flask.ext.simpleldap import LDAP
+from flask_simpleldap import LDAP
 
 app = Flask(__name__)
 app.secret_key = 'dev key'
diff --git a/flask_simpleldap/__init__.py b/flask_simpleldap/__init__.py
index 0c8b264..843097c 100644
--- a/flask_simpleldap/__init__.py
+++ b/flask_simpleldap/__init__.py
@@ -23,9 +23,6 @@ class LDAPException(RuntimeError):
     def __str__(self):
         return self.message
 
-    def __unicode__(self):
-        return self.message
-
 
 class LDAP(object):
     def __init__(self, app=None):
@@ -115,8 +112,8 @@ class LDAP(object):
         conn = self.initialize
         try:
             conn.simple_bind_s(
-                current_app.config['LDAP_USERNAME'].encode('utf-8'),
-                current_app.config['LDAP_PASSWORD'].encode('utf-8'))
+                current_app.config['LDAP_USERNAME'],
+                current_app.config['LDAP_PASSWORD'])
             return conn
         except ldap.LDAPError as e:
             raise LDAPException(self.error(e))
@@ -147,7 +144,7 @@ class LDAP(object):
             return
         try:
             conn = self.initialize
-            conn.simple_bind_s(user_dn, password)
+            conn.simple_bind_s(user_dn.decode('utf-8'), password)
             return True
         except ldap.LDAPError:
             return
@@ -191,7 +188,7 @@ class LDAP(object):
                             dn = records[0][1][
                                 current_app.config['LDAP_OBJECTS_DN']]
                             return dn[0]
-                for k, v in records[0][1].items():
+                for k, v in list(records[0][1].items()):
                     result[k] = v
                 return result
         except ldap.LDAPError as e:
@@ -236,7 +233,7 @@ class LDAP(object):
                             records[0][1]:
                         groups = records[0][1][
                             current_app.config['LDAP_USER_GROUPS_FIELD']]
-                        result = [re.findall('(?:cn=|CN=)(.*?),', group)[0] for
+                        result = [re.findall(b'(?:cn=|CN=)(.*?),', group)[0] for
                                   group in groups]
                         return result
         except ldap.LDAPError as e:
@@ -268,10 +265,11 @@ class LDAP(object):
 
     @staticmethod
     def error(e):
-        if 'desc' in dict(e.message):
-            return dict(e.message)['desc']
+        e = e.args[0]
+        if 'desc' in e:
+            return e['desc']
         else:
-            return e[1]
+            return e[0]
 
     @staticmethod
     def login_required(func):
diff --git a/requirements.txt b/requirements.txt
index 9ac950e..dfb1531 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,2 @@
-Flask==0.10.1
-mock==1.3.0
+Flask==0.11
+mock==2.0.0
diff --git a/setup.py b/setup.py
index 3f76717..b36df43 100644
--- a/setup.py
+++ b/setup.py
@@ -9,7 +9,7 @@ from setuptools import setup
 
 setup(
     name='Flask-SimpleLDAP',
-    version='0.4.0',
+    version='1.0.0',
     url='https://github.com/admiralobvious/flask-simpleldap',
     license='MIT',
     author='Alexandre Ferland',
@@ -21,16 +21,17 @@ setup(
     include_package_data=True,
     platforms='any',
     install_requires=[
-        'Flask>=0.9',
-        'python-ldap'
+        'Flask>=0.10',
+        'pyldap'
     ],
     classifiers=[
         'Environment :: Web Environment',
         'Intended Audience :: Developers',
         'License :: OSI Approved :: MIT License',
         'Operating System :: OS Independent',
-        'Programming Language :: Python :: 2.6',
         'Programming Language :: Python :: 2.7',
+        'Programming Language :: Python :: 3.4',
+        'Programming Language :: Python :: 3.5',
         'Topic :: Software Development :: Libraries :: Python Modules'
     ]
 )
-- 
GitLab