diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 2425b0a1836c83880fd486766478a0eb5226d0fa..0000000000000000000000000000000000000000 --- a/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*~ -*.pyc -*.swp -.tox -MANIFEST -dist/ -.envrc -.direnv diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index bdb971161b78d8225b4df4eeb1c6b56978242ef4..0000000000000000000000000000000000000000 --- a/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: python - -python: - - 3.3 - - 3.2 - -install: - - pip install --use-mirrors Django==1.5 - - python setup.py install -script: ./run_tests.sh diff --git a/CHANGES.md b/CHANGES.md deleted file mode 100644 index eb107a357ce561e0ea88b62dc9c24e465b06b5fa..0000000000000000000000000000000000000000 --- a/CHANGES.md +++ /dev/null @@ -1,43 +0,0 @@ - -As of 3.0.0: - -* API changes - * SQLStore implementations no longer create or use a 'settings' - table - * SRegResponse.fromSuccessResponse returns None when no signed - arguments were found - * Added functions to generate request/response HTML forms with - auto-submission javascript - * Consumer (relying party) API: AuthRequest.htmlMarkup - * Server API: server.OpenIDResponse.toHTML - * PAPE (Provider Authentication Policy Extension) module - * Updated extension for specification draft 2 - * Request.fromSuccessResponse returns None if PAPE response - arguments were not signed - -* New features - * Demo server now supports OP-driven identifier selection - * Demo consumer now has a "stateless" option - * Fetchers now only read/request first megabyte of response - -* Bug fixes - * NOT NULL constraints were added to SQLStore tables where - appropriate - * message.fromPostArgs: use query.items() instead of iteritems(), - fixes #161 (Affects Django users) - * check_authentication requests: copy entire response, not just - signed fields. Fixes missing namespace in check_authentication - requests - * Consumer._verifyDiscoveryResults: fall back to OpenID 1.0 type if - 1.1 endpoint cannot be found; fixes discovery verification bug for - certain OpenID 1 identifiers - * SQLStore._execSQL: convert unicode arguments to str to avoid - postgresql api bug with unicode objects (Thanks to Marek Kuziel.) - * MySQLStore: Use ENGINE instead of TYPE when creating tables - * server.OpenIDResponse.toFormMarkup: Use return_to from the - request, not the response fields (Not all responses (i.e. cancel, - setup_needed) include a return_to field.) - * server.AssociationRequest.answer: include session_type in - no-encryption assoc responses - * OpenIDServiceEndpoint.getDisplayIdentifier: Don't include the - fragment in display identifiers. diff --git a/PKG-INFO b/PKG-INFO new file mode 100644 index 0000000000000000000000000000000000000000..e7a66b80723a0bf4745cad7baf86a9820d148fd0 --- /dev/null +++ b/PKG-INFO @@ -0,0 +1,26 @@ +Metadata-Version: 1.1 +Name: python3-openid +Version: 3.0.9 +Summary: OpenID support for modern servers and consumers. +Home-page: http://github.com/necaris/python3-openid +Author: Rami Chowdhury +Author-email: rami.chowdhury@gmail.com +License: UNKNOWN +Download-URL: http://github.com/necaris/python3-openid/tarball/v3.0.9 +Description: This is a set of Python packages to support use of + the OpenID decentralized identity system in your application, update to Python + 3. Want to enable single sign-on for your web site? Use the openid.consumer + package. Want to run your own OpenID server? Check out openid.server. + Includes example code and support for a variety of storage back-ends. +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Operating System :: POSIX +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Internet :: WWW/HTTP +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: System :: Systems Administration :: Authentication/Directory diff --git a/README.md b/README.md deleted file mode 100644 index a1691c8a5388df5cc5ba34071aef8b212c45b214..0000000000000000000000000000000000000000 --- a/README.md +++ /dev/null @@ -1,53 +0,0 @@ -*NOTE*: This started out as a fork of the Python OpenID library, with changes -to make it Python 3 compatible. It's now a port of that library, including -cleanups and updates to the code in general. - -[](https://travis-ci.org/necaris/python3-openid) - -# REQUIREMENTS - - - Python 3.x (tested on 3.2, 3.3, 3.4) - -# INSTALLATION - -The recommended way is to install from PyPI with `pip`: - - pip install python3-openid - -Alternatively, you can run the following command: - - python setup.py install - - -# GETTING STARTED - -The library should follow the existing `python-openid` API as closely as possible. - -*NOTE*: documentation will be auto-generated as soon as I can figure out how to update the documentation tools. - -*NOTE*: The examples directory includes an example server and consumer -implementation. See the README file in that directory for more -information on running the examples. - -# LOGGING - -This library offers a logging hook that will record unexpected -conditions that occur in library code. If a condition is recoverable, -the library will recover and issue a log message. If it is not -recoverable, the library will raise an exception. See the -documentation for the `openid.oidutil` module for more on the logging -hook. - -# DOCUMENTATION - -The documentation in this library is in Epydoc format, which is -detailed at: - - http://epydoc.sourceforge.net/ - -# CONTACT - -Going forward, the plan is to maintain this library on GitHub, so any bug -reports, suggestions, and feature requests should be raised [here](issues). - -There are also the `#python-openid` and `#openid` channels on FreeNode IRC. diff --git a/admin/runtests b/admin/runtests index b2a3a79f68a9c9904658ae5910bb54ea63ba7abc..1343ea110f5928157b8d39027734ecf225791399 100755 --- a/admin/runtests +++ b/admin/runtests @@ -1,5 +1,8 @@ #!/usr/bin/env python -import os.path, sys, warnings +import os.path +import sys +import unittest + test_modules = [ 'cryptutil', @@ -14,19 +17,19 @@ def fixpath(): d = os.path.dirname(sys.argv[0]) parent = os.path.normpath(os.path.join(d, '..')) if parent not in sys.path: - print "putting %s in sys.path" % (parent,) + print ("putting %s in sys.path" % (parent,)) sys.path.insert(0, parent) def otherTests(): failed = [] for module_name in test_modules: - print 'Testing %s...' % (module_name,) , + print ('Testing %s...' % (module_name,)) sys.stdout.flush() module_name = 'openid.test.' + module_name try: test_mod = __import__(module_name, {}, {}, [None]) except ImportError: - print 'Failed to import test %r' % (module_name,) + print ('Failed to import test %r' % (module_name,)) failed.append(module_name) else: try: @@ -37,7 +40,7 @@ def otherTests(): sys.excepthook(*sys.exc_info()) failed.append(module_name) else: - print 'Succeeded.' + print ('Succeeded.') return failed @@ -72,9 +75,10 @@ def pyunitTests(): try: from openid.test import test_examples - except ImportError, e: + except ImportError as e: if 'twill' in str(e): - warnings.warn("Could not import twill; skipping test_examples.") + raise unittest.SkipTest('Skipping test_examples. ' + 'Could not import twill.') else: raise else: @@ -110,10 +114,10 @@ def pyunitTests(): m = __import__('openid.test.%s' % (name,), {}, {}, ['unused']) try: s.addTest(m.pyUnitTests()) - except AttributeError, ex: + except AttributeError as ex: # because the AttributeError doesn't actually say which # object it was. - print "Error loading tests from %s:" % (name,) + print ("Error loading tests from %s:" % (name,)) raise runner = unittest.TextTestRunner() # verbosity=2) @@ -125,7 +129,7 @@ def pyunitTests(): def splitDir(d, count): # in python2.4 and above, it's easier to spell this as # d.rsplit(os.sep, count) - for i in xrange(count): + for i in range(count): d = os.path.dirname(d) return d @@ -144,7 +148,9 @@ def _import_djopenid(): djinit = os.path.join(djdir, '__init__.py') djopenid = types.ModuleType('djopenid') - execfile(djinit, djopenid.__dict__) + with open(djinit) as f: + code = compile(f.read(), djinit, 'exec') + exec(code, djopenid.__dict__) djopenid.__file__ = djinit # __path__ is the magic that makes child modules of the djopenid package @@ -167,12 +173,11 @@ def django_tests(): try: import django.test.simple - except ImportError, e: - warnings.warn("django.test.simple not found; " - "django examples not tested.") - return 0 + except ImportError as e: + raise unittest.SkipTest("django.test.simple not found; " + "django examples not tested.") import djopenid.server.models, djopenid.consumer.models - print "Testing Django examples:" + print ("Testing Django examples:") # These tests do get put in to a pyunit test suite, so we could run them # with the other pyunit tests, but django also establishes a test database @@ -193,7 +198,7 @@ def main(): django_failures = django_tests() if other_failed: - print 'Failures:', ', '.join(other_failed) + print ('Failures:', ', '.join(other_failed)) failed = (bool(other_failed) or bool(not pyunit_result.wasSuccessful()) or diff --git a/contrib/upgrade-store-1.1-to-2.0 b/contrib/upgrade-store-1.1-to-2.0 index 1f587c357c48ab496301b01163594c2c9004d100..6a346826af565590301d058ebfc54e344e4097c7 100644 --- a/contrib/upgrade-store-1.1-to-2.0 +++ b/contrib/upgrade-store-1.1-to-2.0 @@ -119,13 +119,17 @@ def main(argv=None): return 1 password = askForPassword() try: - import psycopg + import psycopg2 except ImportError: - print "You need psycopg installed to update a postgres DB." - return 1 + try: + from psycopg2cffi import compat + compat.register() + except: + print "You need psycopg2 installed to update a postgres DB." + return 1 try: - db_conn = psycopg.connect(database = options.postgres_db_name, + db_conn = psycopg2.connect(database = options.postgres_db_name, user = options.username, host = options.db_host, password = password) diff --git a/contrib/upgrade-store-1.1-to-2.0~ b/contrib/upgrade-store-1.1-to-2.0~ new file mode 100644 index 0000000000000000000000000000000000000000..2f6f0ebd6ad73ab6ab6ddcfc6304faa479c85f45 --- /dev/null +++ b/contrib/upgrade-store-1.1-to-2.0~ @@ -0,0 +1,170 @@ +#!/usr/bin/env python +# SQL Store Upgrade Script +# for version 1.x to 2.0 of the OpenID library. +# Doesn't depend on the openid library, so you can run this python +# script to update databases for ruby or PHP as well. +# +# Testers note: +# +# A SQLite3 db with the 1.2 schema exists in +# openid/test/data/openid-1.2-consumer-sqlitestore.db if you want something +# to try upgrading. +# +# TODO: +# * test data for mysql and postgresql. +# * automated tests. + +import os +import getpass +import sys +from optparse import OptionParser + + +def askForPassword(): + return getpass.getpass("DB Password: ") + +def askForConfirmation(dbname,tablename): + print """The table %s from the database %s will be dropped, and + an empty table with the new nonce table schema will replace it."""%( + tablename, dbname) + return raw_input("Continue? ").lower().strip().startswith('y') + +def doSQLiteUpgrade(db_conn, nonce_table_name='oid_nonces'): + cur = db_conn.cursor() + cur.execute('DROP TABLE %s'%nonce_table_name) + sql = """ + CREATE TABLE %s ( + server_url VARCHAR, + timestamp INTEGER, + salt CHAR(40), + UNIQUE(server_url, timestamp, salt) + ); + """%nonce_table_name + cur.execute(sql) + cur.close() + +def doMySQLUpgrade(db_conn, nonce_table_name='oid_nonces'): + cur = db_conn.cursor() + cur.execute('DROP TABLE %s'%nonce_table_name) + sql = """ + CREATE TABLE %s ( + server_url BLOB, + timestamp INTEGER, + salt CHAR(40), + PRIMARY KEY (server_url(255), timestamp, salt) + ) + TYPE=InnoDB; + """%nonce_table_name + cur.execute(sql) + cur.close() + +def doPostgreSQLUpgrade(db_conn, nonce_table_name='oid_nonces'): + cur = db_conn.cursor() + cur.execute('DROP TABLE %s'%nonce_table_name) + sql = """ + CREATE TABLE %s ( + server_url VARCHAR(2047), + timestamp INTEGER, + salt CHAR(40), + PRIMARY KEY (server_url, timestamp, salt) + ); + """%nonce_table_name + cur.execute(sql) + cur.close() + db_conn.commit() + +def main(argv=None): + parser = OptionParser() + parser.add_option("-u", "--user", dest="username", + default=os.environ.get('USER'), + help="User name to use to connect to the DB. " + "Defaults to USER environment variable.") + parser.add_option('-t', '--table', dest='tablename', default='oid_nonces', + help='The name of the nonce table to drop and recreate. ' + ' Defaults to "oid_nonces", the default table name for ' + 'the openid stores.') + parser.add_option('--mysql', dest='mysql_db_name', + help='Upgrade a table from this MySQL database. ' + 'Requires username for database.') + parser.add_option('--pg', '--postgresql', dest='postgres_db_name', + help='Upgrade a table from this PostgreSQL database. ' + 'Requires username for database.') + parser.add_option('--sqlite', dest='sqlite_db_name', + help='Upgrade a table from this SQLite database file.') + parser.add_option('--host', dest='db_host', + default='localhost', + help='Host on which to find MySQL or PostgreSQL DB.') + (options, args) = parser.parse_args(argv) + + db_conn = None + + if options.sqlite_db_name: + try: + from pysqlite2 import dbapi2 as sqlite + except ImportError: + print "You must have pysqlite2 installed in your PYTHONPATH." + return 1 + try: + db_conn = sqlite.connect(options.sqlite_db_name) + except Exception, e: + print "Could not connect to SQLite database:", str(e) + return 1 + + if askForConfirmation(options.sqlite_db_name, options.tablename): + doSQLiteUpgrade(db_conn, nonce_table_name=options.tablename) + + if options.postgres_db_name: + if not options.username: + print "A username is required to open a PostgreSQL Database." + return 1 + password = askForPassword() + try: + import psycopg2 + except ImportError: + print "You need psycopg2 installed to update a postgres DB." + return 1 + + try: + db_conn = psycopg2.connect(database = options.postgres_db_name, + user = options.username, + host = options.db_host, + password = password) + except Exception, e: + print "Could not connect to PostgreSQL database:", str(e) + return 1 + + if askForConfirmation(options.postgres_db_name, options.tablename): + doPostgreSQLUpgrade(db_conn, nonce_table_name=options.tablename) + + if options.mysql_db_name: + if not options.username: + print "A username is required to open a MySQL Database." + return 1 + password = askForPassword() + try: + import MySQLdb + except ImportError: + print "You must have MySQLdb installed to update a MySQL DB." + return 1 + + try: + db_conn = MySQLdb.connect(options.db_host, options.username, + password, options.mysql_db_name) + except Exception, e: + print "Could not connect to MySQL database:", str(e) + return 1 + + if askForConfirmation(options.mysql_db_name, options.tablename): + doMySQLUpgrade(db_conn, nonce_table_name=options.tablename) + + if db_conn: + db_conn.close() + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + retval = main() + sys.exit(retval) diff --git a/dev-requirements.txt b/dev-requirements.txt deleted file mode 100644 index d6792cc1ce17ee9522046630324b272e6bbda0da..0000000000000000000000000000000000000000 --- a/dev-requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -# -nose==1.3.1 -Django diff --git a/examples/README b/examples/README deleted file mode 100644 index 87c0831944666409677e4964fd422245ef7dfd85..0000000000000000000000000000000000000000 --- a/examples/README +++ /dev/null @@ -1,91 +0,0 @@ -Python OpenID library example code -================================== - -The examples directory contains working code illustrating the use of -the library for performing OpenID authentication, both as a consumer -and a server. There are two kinds of examples, one that can run -without any external dependencies, and one that uses the Django Web -framework. The examples do not illustrate how to use all of the -features of the library, but they should be a good starting point to -see how to use this library with your code. - -Both the Django libraries and the BaseHTTPServer examples require that -the OpenID library is installed or that it has been added to Python's -search path (PYTHONPATH environment variable or sys.path). - -The Django example is probably a good place to start reading the -code. There is little that is Django-specific about the OpenID logic -in the example, and it should be easy to port to any framework. To run -the django examples, see the README file in the djopenid subdirectory. - -The other examples use Python's built-in BaseHTTPServer and have a -good deal of ad-hoc dispatching and rendering code mixed in - -Using the BaseHTTPServer examples -================================= - -This directory contains a working server and consumer that use this -OpenID library. They are both written using python's standard -BaseHTTPServer. - - -To run the example system: - -1. Make sure you've installed the library, as explained in the - installation instructions. - -2. Start the consumer server: - - python consumer.py --port 8001 - - -3. In another terminal, start the identity server: - - python server.py --port 8000 - - (Hit Ctrl-C in either server's window to stop that server.) - - -4. Open your web broswer, and go to the consumer server: - - http://localhost:8001/ - - Note that all pages the consumer server shows will have "Python OpenID - Consumer Example" across the top. - - -5. Enter an identity url managed by the sample identity server: - - http://localhost:8000/id/bob - - -6. The browser will be redirected to the sample server, which will be - requesting that you log in to proceed. Enter the username for the - identity URL into the login box: - - bob - - Note that all pages the identity server shows will have "Python - OpenID Server Example" across the top. - - -7. After you log in as bob, the server example will ask you if you - want to allow http://localhost:8001/ to know your identity. Say - yes. - - -8. You should end up back on the consumer site, at a page indicating - you've logged in successfully. - - -That's a basic OpenID login procedure. You can continue through it, -playing with variations to see how they work. The python code is -intended to be a straightforward example of how to use the python -OpenID library to function as either an identity server or consumer. - -Getting help -============ - -Please send bug reports, patches, and other feedback to - - http://openid.net/developers/dev-mailing-lists/ diff --git a/examples/djopenid/README b/examples/djopenid/README deleted file mode 100644 index 2d28b473f61ec5bb5f1a82f3959c39fb4f9843e7..0000000000000000000000000000000000000000 --- a/examples/djopenid/README +++ /dev/null @@ -1,54 +0,0 @@ -DJANGO EXAMPLE PACKAGE -====================== - -This package implements an example consumer and server for the Django -Python web framework. You can get Django (and learn more about it) at - - http://www.djangoproject.com/ - -SETUP -===== - - 1. Install the OpenID library - - 2. Install Django >= 1.5 (with Python 3 support) - - 3. Modify djopenid/settings.py appropriately; you may wish to change - the database type or path, although the default settings should be - sufficient for most systems. - - 4. In examples/djopenid/ run: - - python manage.py syncdb - - 5. To run the example consumer or server, run - - python manage.py runserver PORT - - where PORT is the port number on which to listen. - - Note that if you want to try both the consumer and server at the - same time, run the command twice with two different values for - PORT. - - 6. Point your web browser at the server at - - http://localhost:PORT/ - - to begin. - -ABOUT THE CODE -============== - -The example server and consumer code provided in this package are -intended to be instructional in the use of this OpenID library. While -it is not recommended to use the example code in production, the code -should be sufficient to explain the general use of the library. - -If you aren't familiar with the Django web framework, you can quickly -start looking at the important code by looking in the 'views' modules: - - djopenid.consumer.views - djopenid.server.views - -Each view is a python callable that responds to an HTTP request. diff --git a/examples/djopenid/server/tests.py b/examples/djopenid/server/tests.py index 8ac86fa0ff342bc509f38cc90a5618a335ce7e28..de5f1e924cef06c528854246f17d08f91ea468e2 100644 --- a/examples/djopenid/server/tests.py +++ b/examples/djopenid/server/tests.py @@ -43,22 +43,22 @@ class TestProcessTrustResult(TestCase): response = views.processTrustResult(self.request) - self.failUnlessEqual(response.status_code, 302) + self.assertEqual(response.status_code, 302) finalURL = response['location'] - self.failUnless('openid.mode=id_res' in finalURL, finalURL) - self.failUnless('openid.identity=' in finalURL, finalURL) - self.failUnless('openid.sreg.postcode=12345' in finalURL, finalURL) + self.assertIn('openid.mode=id_res', finalURL) + self.assertIn('openid.identity=', finalURL) + self.assertIn('openid.sreg.postcode=12345', finalURL) def test_cancel(self): self.request.POST['cancel'] = 'Yes' response = views.processTrustResult(self.request) - self.failUnlessEqual(response.status_code, 302) + self.assertEqual(response.status_code, 302) finalURL = response['location'] - self.failUnless('openid.mode=cancel' in finalURL, finalURL) - self.failIf('openid.identity=' in finalURL, finalURL) - self.failIf('openid.sreg.postcode=12345' in finalURL, finalURL) + self.assertIn('openid.mode=cancel', finalURL) + self.assertNotIn('openid.identity=', finalURL) + self.assertNotIn('openid.sreg.postcode=12345', finalURL) class TestShowDecidePage(TestCase): @@ -98,6 +98,6 @@ class TestGenericXRDS(TestCase): requested_url = 'http://requested.invalid/' (endpoint,) = applyFilter(requested_url, response.content) - self.failUnlessEqual(YADIS_CONTENT_TYPE, response['Content-Type']) - self.failUnlessEqual(type_uris, endpoint.type_uris) - self.failUnlessEqual(endpoint_url, endpoint.uri) + self.assertEqual(YADIS_CONTENT_TYPE, response['Content-Type']) + self.assertEqual(type_uris, endpoint.type_uris) + self.assertEqual(endpoint_url, endpoint.uri) diff --git a/examples/djopenid/settings.py b/examples/djopenid/settings.py index 1a33dcfdc80b92285b0f963a81e99413d4cdfa73..b1ccc2699a05f5baaa9815c0c7162a4eac9c7212 100644 --- a/examples/djopenid/settings.py +++ b/examples/djopenid/settings.py @@ -38,6 +38,7 @@ TIME_ZONE = 'Europe/London' # http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes # http://blogs.law.harvard.edu/tech/stories/storyReader$15 LANGUAGE_CODE = 'en-us.UTF-8' +USE_I18N = False SITE_ID = 1 diff --git a/examples/djopenid/util.py b/examples/djopenid/util.py index f37a4d04a0003502291862e71112b5aaa0c07311..fc21ceb5c78397e9f1f55bf9436e4bf2067f2d54 100644 --- a/examples/djopenid/util.py +++ b/examples/djopenid/util.py @@ -2,7 +2,6 @@ """ Utility code for the Django example consumer and server. """ - from urllib.parse import urljoin from django.db import connection @@ -15,6 +14,12 @@ from django.shortcuts import render_to_response from django.conf import settings +try: + import psycopg2 +except ImportError: + from psycopg2cffi import compat + compat.register() + from openid.store.filestore import FileOpenIDStore from openid.store import sqlstore from openid.yadis.constants import YADIS_CONTENT_TYPE diff --git a/openid/__init__.py b/openid/__init__.py index 25eaaaae000c856837ad85ccdedc775ee31c9e16..8577355396434f9a5c26a52b02e839e317be7745 100644 --- a/openid/__init__.py +++ b/openid/__init__.py @@ -23,7 +23,7 @@ module. and limitations under the License. """ -version_info = (3, 0, 4) +version_info = (3, 0, 9) __version__ = ".".join(str(x) for x in version_info) diff --git a/openid/fetchers.py b/openid/fetchers.py index 469e733ecdcc5479e4bbaf11e86b412a60866dca..68ff06976f5032c0b6d13da5e5469211ed73a98d 100644 --- a/openid/fetchers.py +++ b/openid/fetchers.py @@ -496,7 +496,7 @@ class HTTPLib2Fetcher(HTTPFetcher): final_url = url return HTTPResponse( - body=content, + body=content.decode(), # TODO Don't assume ASCII final_url=final_url, headers=dict(list(httplib2_response.items())), status=httplib2_response.status, diff --git a/openid/oidutil.py b/openid/oidutil.py index dbbba126e505faeb5e5380dc60dc76440b4d204d..70637c44e21d019530a36861e09a1b1e90d69e62 100644 --- a/openid/oidutil.py +++ b/openid/oidutil.py @@ -11,12 +11,17 @@ __all__ = ['log', 'appendArgs', 'toBase64', 'fromBase64', 'autoSubmitHTML', import binascii import logging -import urllib.parse as urlparse +# import urllib.parse as urlparse from urllib.parse import urlencode +xxe_safe_elementtree_modules = [ + 'defusedxml.cElementTree', + 'defusedxml.ElementTree', + ] + + elementtree_modules = [ - 'lxml.etree', 'xml.etree.cElementTree', 'xml.etree.ElementTree', 'cElementTree', @@ -61,6 +66,27 @@ for (var i = 0; i < elements.length; i++) { return html +def importSafeElementTree(module_names=None): + """Find a working ElementTree implementation that is not vulnerable + to XXE, using `defusedxml`. + + >>> XXESafeElementTree = importSafeElementTree() + + @param module_names: The names of modules to try to use as + a safe ElementTree. Defaults to C{L{xxe_safe_elementtree_modules}} + + @returns: An ElementTree module that is not vulnerable to XXE. + """ + if module_names is None: + module_names = xxe_safe_elementtree_modules + try: + return importElementTree(module_names) + except ImportError: + raise ImportError('Unable to find a ElementTree module ' + 'that is not vulnerable to XXE. ' + 'Tried importing %r' % (module_names,)) + + def importElementTree(module_names=None): """Find a working ElementTree implementation, trying the standard places that such a thing might show up. diff --git a/openid/store/sqlstore.py b/openid/store/sqlstore.py index 2c6e4082c15ecb017a3fd11da1cc21186f09b349..690ed19bc61aba05f76b8bb1a98ba34b556c98f3 100644 --- a/openid/store/sqlstore.py +++ b/openid/store/sqlstore.py @@ -10,6 +10,12 @@ python -c 'from openid.store import sqlstore; import pysqlite2.dbapi2;' import re import time +try: + import psycopg2 +except ImportError: + from psycopg2cffi import compat + compat.register() + from openid.association import Association from openid.store.interface import OpenIDStore from openid.store import nonce @@ -228,6 +234,8 @@ class SQLStore(OpenIDStore): else: associations = [] for values in rows: + values = list(values) + values[1] = self.blobDecode(values[1]) assoc = Association(*values) if assoc.expiresIn == 0: self.txn_removeAssociation(server_url, assoc.handle) @@ -339,9 +347,6 @@ class SQLiteStore(SQLStore): clean_nonce_sql = 'DELETE FROM %(nonces)s WHERE timestamp < ?;' - def blobDecode(self, buf): - return str(buf) - def blobEncode(self, s): return memoryview(s) @@ -417,13 +422,6 @@ class MySQLStore(SQLStore): clean_nonce_sql = 'DELETE FROM %(nonces)s WHERE timestamp < %%s;' - def blobDecode(self, blob): - if type(blob) is str: - # Versions of MySQLdb >= 1.2.2 - return blob - else: - # Versions of MySQLdb prior to 1.2.2 (as far as we can tell) - return blob.tostring() class PostgreSQLStore(SQLStore): """ @@ -434,16 +432,7 @@ class PostgreSQLStore(SQLStore): All other methods are implementation details. """ - - try: - import psycopg as exceptions - except ImportError: - # psycopg2 has the dbapi extension where the exception classes - # are available on the connection object. A psycopg2 - # connection will use the correct exception classes because of - # this, and a psycopg connection will fall through to use the - # psycopg imported above. - exceptions = None + exceptions = None create_nonce_sql = """ CREATE TABLE %(nonces)s ( @@ -510,9 +499,9 @@ class PostgreSQLStore(SQLStore): clean_nonce_sql = 'DELETE FROM %(nonces)s WHERE timestamp < %%s;' def blobEncode(self, blob): - try: - from psycopg2 import Binary - except ImportError: - from psycopg import Binary + from psycopg2 import Binary return Binary(blob) + + def blobDecode(self, blob): + return blob.tobytes() diff --git a/openid/test/__init__.py b/openid/test/__init__.py index 266929737d664fe0f48fc03c0c427fac1a75421d..cb3c3b2169a593150cf979fa08ddcbda3e643047 100644 --- a/openid/test/__init__.py +++ b/openid/test/__init__.py @@ -154,8 +154,8 @@ def djangoExampleTests(): try: import django.test.simple except ImportError: - warnings.warn("django.test.simple not found; skipping django examples.") - return 0 + raise unittest.SkipTest("Skipping django examples. " + "django.test.simple not found.") import djopenid.server.models import djopenid.consumer.models diff --git a/openid/test/storetest.py b/openid/test/storetest.py index 159e424a8351b1af437d316c6482b5449af2cc44..9aadb245f5197a5ddfa1aa6910bd2ef85d51c9a4 100644 --- a/openid/test/storetest.py +++ b/openid/test/storetest.py @@ -1,16 +1,21 @@ import unittest import string import time -import socket -import random import os -import warnings +import uuid + +try: + import psycopg2 +except ImportError: + from psycopg2cffi import compat + compat.register() from openid.association import Association from openid.cryptutil import randomString from openid.store.nonce import mkNonce, split -db_host = 'dbtest' + +db_host = os.environ.get('TEST_DB_HOST', 'dbtest') allowed_handle = [] for c in string.printable: @@ -27,12 +32,12 @@ generateSecret = randomString def getTmpDbName(): - hostname = socket.gethostname() - hostname = hostname.replace('.', '_') - hostname = hostname.replace('-', '_') - return "%s_%d_%s_openid_test" % \ - (hostname, os.getpid(), \ - random.randrange(1, int(time.time()))) + """Returns a name suitable for creating a temporary database. + + Restrictions: + - Maximum length 64 characters (MySQL) + """ + return "openid_test_%s" % uuid.uuid4().hex def testStore(store): @@ -55,7 +60,7 @@ def testStore(store): def checkRetrieve(url, handle=None, expected=None): retrieved_assoc = store.getAssociation(url, handle) - assert retrieved_assoc == expected, (retrieved_assoc, expected) + assert retrieved_assoc == expected, (retrieved_assoc.__dict__, expected.__dict__) if expected is not None: if retrieved_assoc is expected: print ('Unexpected: retrieved a reference to the expected ' @@ -250,15 +255,15 @@ def test_sqlite(): def test_mysql(): - # TODO fix from openid.store import sqlstore try: import MySQLdb except ImportError: - warnings.warn("Could not import MySQLdb. Skipping MySQL store tests.") - pass + raise unittest.SkipTest('Skipping MySQL store tests. ' + 'Could not import MySQLdb.') + else: - db_user = 'openid_test' + db_user = os.environ.get('TEST_MYSQL_USER', 'openid_test') db_passwd = '' db_name = getTmpDbName() @@ -269,10 +274,10 @@ def test_mysql(): conn = MySQLdb.connect(user=db_user, passwd=db_passwd, host=db_host) except MySQLdb.OperationalError as why: - if int(why) == 2005: - print(('Skipping MySQL store test (cannot connect ' - 'to test server on host %r)' % (db_host,))) - return + if why.args[0] == 2005: + raise unittest.SkipTest('Skipping MySQL store test. ' + 'Cannot connect to server on host %r.' + % (db_host,)) else: raise @@ -298,7 +303,7 @@ def test_postgresql(): Tests the PostgreSQLStore on a locally-hosted PostgreSQL database cluster, version 7.4 or later. To run this test, you must have: - - The 'psycopg' python module (version 1.1) installed + - The 'psycopg2' python module (version 1.1) installed - PostgreSQL running locally @@ -321,19 +326,24 @@ def test_postgresql(): """ from openid.store import sqlstore try: - import psycopg + import psycopg2 except ImportError: - warnings.warn("Could not import psycopg. Skipping PostgreSQL store tests.") - pass + raise unittest.SkipTest('Skipping PostgreSQL store tests. ' + 'Could not import psycopg2.') else: db_name = getTmpDbName() - db_user = 'openid_test' + db_user = os.environ.get('TEST_POSTGRES_USER', 'openid_test') # Connect once to create the database; reconnect to access the # new database. - conn_create = psycopg.connect(database='template1', user=db_user, - host=db_host) - conn_create.autocommit() + try: + conn_create = psycopg2.connect(database='template1', user=db_user, + host=db_host) + except psycopg2.OperationalError as why: + raise unittest.SkipTest('Skipping PostgreSQL store test: %s' + % why) + + conn_create.autocommit = True # Create the test database. cursor = conn_create.cursor() @@ -341,7 +351,7 @@ def test_postgresql(): conn_create.close() # Connect to the test database. - conn_test = psycopg.connect(database=db_name, user=db_user, + conn_test = psycopg2.connect(database=db_name, user=db_user, host=db_host) # OK, we're in the right environment. Create the store @@ -363,9 +373,9 @@ def test_postgresql(): time.sleep(1) # Remove the database now that the test is over. - conn_remove = psycopg.connect(database='template1', user=db_user, + conn_remove = psycopg2.connect(database='template1', user=db_user, host=db_host) - conn_remove.autocommit() + conn_remove.autocommit = True cursor = conn_remove.cursor() cursor.execute('DROP DATABASE %s;' % (db_name,)) diff --git a/openid/test/test_examples.py b/openid/test/test_examples.py index 16ab8d3b3fd344e8fb3d74d032fdb1a1ef2484a4..9ddbfdedf17bb81e8fa3bbb6bc335f84b4fb4b5b 100644 --- a/openid/test/test_examples.py +++ b/openid/test/test_examples.py @@ -7,6 +7,8 @@ import sys import time from io import StringIO +# TODO: Replace twill with MechanicalSoup or similar +''' import twill.commands import twill.parse import twill.unit @@ -177,7 +179,7 @@ class TestServer(unittest.TestCase): def tearDown(self): twill.set_output(None) twill.set_errout(None) - +''' if __name__ == '__main__': unittest.main() diff --git a/openid/test/test_fetchers.py b/openid/test/test_fetchers.py index 8e9f5def776c968693ea84d17b15443fa67e734f..c97ffbaf2417f1a003e8cf659db098c2519adcb8 100644 --- a/openid/test/test_fetchers.py +++ b/openid/test/test_fetchers.py @@ -107,10 +107,9 @@ def run_fetcher_tests(server): try: __import__(library_name) except ImportError: - warnings.warn( + raise unittest.SkipTest( 'Skipping tests for %r fetcher because ' 'the library did not import.' % (library_name,)) - pass else: assert False, ('%s present but not detected' % ( library_name,)) diff --git a/openid/test/test_parsehtml.py b/openid/test/test_parsehtml.py index b3c647577844207dc9983b533a27d9fd140c0936..387ddc55a0a2374627ebc18f6d9d68f766f4094c 100644 --- a/openid/test/test_parsehtml.py +++ b/openid/test/test_parsehtml.py @@ -1,4 +1,3 @@ -from html.parser import HTMLParseError import os.path import unittest import sys @@ -33,8 +32,6 @@ class _TestCase(unittest.TestCase): msg = "%r != %r for case %s" % (found, self.expected, self.case) self.assertEqual(found, self.expected, msg) - except HTMLParseError: - self.assertTrue(self.expected == 'None', (self.case, self.expected)) else: self.assertTrue(self.expected == 'EOF', (self.case, self.expected)) diff --git a/openid/test/test_rpverify.py b/openid/test/test_rpverify.py index 75829120d9ac802d87484310eabb917125fd3e98..bd877ab2d60e939c43bd79ef5d896ae8968ba871 100644 --- a/openid/test/test_rpverify.py +++ b/openid/test/test_rpverify.py @@ -75,6 +75,13 @@ class TestExtractReturnToURLs(unittest.TestCase): def test_badXML(self): self.failUnlessDiscoveryFailure('>') + def test_failure(self): + try: + self.failUnlessDiscoveryFailure('') + except Exception as e: + print(e) + raise + def test_noEntries(self): self.failUnlessXRDSHasReturnURLs(b'''\ <?xml version="1.0" encoding="UTF-8"?> diff --git a/openid/yadis/etxrd.py b/openid/yadis/etxrd.py index ee0c5dd67aa682cc77c6e83833c44a7330e9e4d2..b42e2acf5c780452569534fe1a13e08efac08693 100644 --- a/openid/yadis/etxrd.py +++ b/openid/yadis/etxrd.py @@ -25,21 +25,10 @@ import functools from datetime import datetime from time import strptime -from openid.oidutil import importElementTree -ElementTree = importElementTree() +from openid.oidutil import importElementTree, importSafeElementTree -# the different elementtree modules don't have a common exception -# model. We just want to be able to catch the exceptions that signify -# malformed XML data and wrap them, so that the other library code -# doesn't have to know which XML library we're using. -try: - # Make the parser raise an exception so we can sniff out the type - # of exceptions - ElementTree.XML('> purposely malformed XML <') -except (SystemExit, MemoryError, AssertionError, ImportError): - raise -except: - XMLError = sys.exc_info()[0] +ElementTree = importElementTree() +SafeElementTree = importSafeElementTree() from openid.yadis import xri @@ -66,8 +55,10 @@ def parseXRDS(text): not contain an XRDS. """ try: - element = ElementTree.XML(text) - except XMLError as why: + element = SafeElementTree.XML(text) + except (SystemExit, MemoryError, AssertionError, ImportError): + raise + except Exception as why: exc = XRDSError('Error parsing document as XML') exc.reason = why raise exc @@ -187,8 +178,7 @@ def getCanonicalID(iname, xrd_tree): childID = canonicalID.lower() for xrd in xrd_list[1:]: - # XXX: can't use rsplit until we require python >= 2.4. - parent_sought = childID[:childID.rindex('!')] + parent_sought = childID.rsplit("!", 1)[0] parent = xri.XRI(xrd.findtext(canonicalID_tag)) if parent_sought != parent.lower(): raise XRDSFraud("%r can not come from %s" % (childID, parent)) diff --git a/openid/yadis/parsehtml.py b/openid/yadis/parsehtml.py index 42cd91e89450239cf8c61bdb1f8a062a56373e4f..c78711196c8ad2d56af07d1f12b1b9d65b078d07 100644 --- a/openid/yadis/parsehtml.py +++ b/openid/yadis/parsehtml.py @@ -1,8 +1,9 @@ __all__ = ['findHTMLMeta', 'MetaNotFound'] -from html.parser import HTMLParser, HTMLParseError +from html.parser import HTMLParser import html.entities import re +import sys from openid.yadis.constants import YADIS_HEADER_NAME @@ -96,7 +97,13 @@ class YadisHTMLParser(HTMLParser): TERMINATED = 4 def __init__(self): - super(YadisHTMLParser, self).__init__(strict=False) + if (sys.version_info.minor <= 2): + # Python 3.2 and below actually require the `strict` argument + # to `html.parser.HTMLParser` -- otherwise it's deprecated and + # we don't want to pass it + super(YadisHTMLParser, self).__init__(strict=False) + else: + super(YadisHTMLParser, self).__init__() self.phase = self.TOP def _terminate(self): @@ -187,10 +194,6 @@ def findHTMLMeta(stream): chunks.append(chunk) try: parser.feed(chunk) - except HTMLParseError as why: - # HTML parse error, so bail - chunks.append(stream.read()) - break except ParseDone as why: uri = why.args[0] if uri is None: diff --git a/pylintrc b/pylintrc deleted file mode 100644 index fb36e4c06d86fd80817e6c2cab7b6b37bdbec63f..0000000000000000000000000000000000000000 --- a/pylintrc +++ /dev/null @@ -1,40 +0,0 @@ -[REPORTS] - -include-ids=y - -[BASIC] - -# Required attributes for module, separated by a comma -required-attributes=__all__ - -# Regular expression which should only match functions or classes name which do -# not require a docstring -no-docstring-rgx=__.*__ - -# Regular expression which should only match correct module names -module-rgx=[a-z_][a-z0-9_]*$ - -# Regular expression which should only match correct module level names -const-rgx=(([a-z_][a-z0-9_]{3,30})|(__.*__)|([A-Z_][A-Z0-9_]{3,30}))$ - -# Regular expression which should only match correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - -# Regular expression which should only match correct function names -function-rgx=[a-z_][A-Za-z0-9_]{2,30}$ - -# Regular expression which should only match correct method names -method-rgx=[a-z_][A-Za-z0-9_]{2,30}$ - -# Regular expression which should only match correct list comprehension / -# generator expression variable names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# List of builtins function names that should not be used, separated by a comma -bad-functions=input diff --git a/python3_openid.egg-info/PKG-INFO b/python3_openid.egg-info/PKG-INFO new file mode 100644 index 0000000000000000000000000000000000000000..e7a66b80723a0bf4745cad7baf86a9820d148fd0 --- /dev/null +++ b/python3_openid.egg-info/PKG-INFO @@ -0,0 +1,26 @@ +Metadata-Version: 1.1 +Name: python3-openid +Version: 3.0.9 +Summary: OpenID support for modern servers and consumers. +Home-page: http://github.com/necaris/python3-openid +Author: Rami Chowdhury +Author-email: rami.chowdhury@gmail.com +License: UNKNOWN +Download-URL: http://github.com/necaris/python3-openid/tarball/v3.0.9 +Description: This is a set of Python packages to support use of + the OpenID decentralized identity system in your application, update to Python + 3. Want to enable single sign-on for your web site? Use the openid.consumer + package. Want to run your own OpenID server? Check out openid.server. + Includes example code and support for a variety of storage back-ends. +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Operating System :: POSIX +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Topic :: Internet :: WWW/HTTP +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: System :: Systems Administration :: Authentication/Directory diff --git a/python3_openid.egg-info/SOURCES.txt b/python3_openid.egg-info/SOURCES.txt new file mode 100644 index 0000000000000000000000000000000000000000..db6fea429213a05a19ebda1c916505f2af8fa72b --- /dev/null +++ b/python3_openid.egg-info/SOURCES.txt @@ -0,0 +1,176 @@ +LICENSE +MANIFEST.in +NEWS.md +background-associations.txt +setup.cfg +setup.py +admin/builddiscover.py +admin/fixperms +admin/gettlds.py +admin/runtests +admin/setversion +contrib/associate +contrib/openid-parse +contrib/upgrade-store-1.1-to-2.0 +contrib/upgrade-store-1.1-to-2.0~ +examples/__init__.py +examples/consumer.py +examples/discover +examples/server.py +examples/djopenid/__init__.py +examples/djopenid/manage.py +examples/djopenid/settings.py +examples/djopenid/urls.py +examples/djopenid/util.py +examples/djopenid/views.py +examples/djopenid/consumer/__init__.py +examples/djopenid/consumer/models.py +examples/djopenid/consumer/urls.py +examples/djopenid/consumer/views.py +examples/djopenid/server/__init__.py +examples/djopenid/server/models.py +examples/djopenid/server/tests.py +examples/djopenid/server/urls.py +examples/djopenid/server/views.py +examples/djopenid/templates/index.html +examples/djopenid/templates/xrds.xml +examples/djopenid/templates/consumer/index.html +examples/djopenid/templates/consumer/request_form.html +examples/djopenid/templates/server/endpoint.html +examples/djopenid/templates/server/idPage.html +examples/djopenid/templates/server/index.html +examples/djopenid/templates/server/pape_request_info.html +examples/djopenid/templates/server/trust.html +openid/__init__.py +openid/association.py +openid/codecutil.py +openid/cryptutil.py +openid/dh.py +openid/extension.py +openid/fetchers.py +openid/kvform.py +openid/message.py +openid/oidutil.py +openid/sreg.py +openid/urinorm.py +openid/consumer/__init__.py +openid/consumer/consumer.py +openid/consumer/discover.py +openid/consumer/html_parse.py +openid/extensions/__init__.py +openid/extensions/ax.py +openid/extensions/sreg.py +openid/extensions/draft/__init__.py +openid/extensions/draft/pape2.py +openid/extensions/draft/pape5.py +openid/server/__init__.py +openid/server/server.py +openid/server/trustroot.py +openid/store/__init__.py +openid/store/filestore.py +openid/store/interface.py +openid/store/memstore.py +openid/store/nonce.py +openid/store/sqlstore.py +openid/test/__init__.py +openid/test/cryptutil.py +openid/test/datadriven.py +openid/test/dh.py +openid/test/dhpriv +openid/test/discoverdata.py +openid/test/kvform.py +openid/test/linkparse.py +openid/test/linkparse.txt +openid/test/n2b64 +openid/test/oidutil.py +openid/test/storetest.py +openid/test/support.py +openid/test/test_accept.py +openid/test/test_association.py +openid/test/test_association_response.py +openid/test/test_auth_request.py +openid/test/test_ax.py +openid/test/test_codecutil.py +openid/test/test_consumer.py +openid/test/test_discover.py +openid/test/test_etxrd.py +openid/test/test_examples.py +openid/test/test_extension.py +openid/test/test_fetchers.py +openid/test/test_htmldiscover.py +openid/test/test_message.py +openid/test/test_negotiation.py +openid/test/test_nonce.py +openid/test/test_openidyadis.py +openid/test/test_pape.py +openid/test/test_pape_draft2.py +openid/test/test_pape_draft5.py +openid/test/test_parsehtml.py +openid/test/test_rpverify.py +openid/test/test_server.py +openid/test/test_services.py +openid/test/test_sreg.py +openid/test/test_symbol.py +openid/test/test_urinorm.py +openid/test/test_verifydisco.py +openid/test/test_xri.py +openid/test/test_xrires.py +openid/test/test_yadis_discover.py +openid/test/trustroot.py +openid/test/urinorm.txt +openid/test/data/accept.txt +openid/test/data/example-xrds.xml +openid/test/data/openid-1.2-consumer-sqlitestore.db +openid/test/data/test1-discover.txt +openid/test/data/test1-parsehtml.txt +openid/test/data/trustroot.txt +openid/test/data/test_discover/openid.html +openid/test/data/test_discover/openid2.html +openid/test/data/test_discover/openid2_xrds.xml +openid/test/data/test_discover/openid2_xrds_no_local_id.xml +openid/test/data/test_discover/openid_1_and_2.html +openid/test/data/test_discover/openid_1_and_2_xrds.xml +openid/test/data/test_discover/openid_1_and_2_xrds_bad_delegate.xml +openid/test/data/test_discover/openid_and_yadis.html +openid/test/data/test_discover/openid_no_delegate.html +openid/test/data/test_discover/unicode.html +openid/test/data/test_discover/unicode3.html +openid/test/data/test_discover/yadis_0entries.xml +openid/test/data/test_discover/yadis_2_bad_local_id.xml +openid/test/data/test_discover/yadis_2entries_delegate.xml +openid/test/data/test_discover/yadis_2entries_idp.xml +openid/test/data/test_discover/yadis_another_delegate.xml +openid/test/data/test_discover/yadis_idp.xml +openid/test/data/test_discover/yadis_idp_delegate.xml +openid/test/data/test_discover/yadis_no_delegate.xml +openid/test/data/test_etxrd/README +openid/test/data/test_etxrd/delegated-20060809-r1.xrds +openid/test/data/test_etxrd/delegated-20060809-r2.xrds +openid/test/data/test_etxrd/delegated-20060809.xrds +openid/test/data/test_etxrd/no-xrd.xml +openid/test/data/test_etxrd/not-xrds.xml +openid/test/data/test_etxrd/prefixsometimes.xrds +openid/test/data/test_etxrd/ref.xrds +openid/test/data/test_etxrd/sometimesprefix.xrds +openid/test/data/test_etxrd/spoof1.xrds +openid/test/data/test_etxrd/spoof2.xrds +openid/test/data/test_etxrd/spoof3.xrds +openid/test/data/test_etxrd/status222.xrds +openid/test/data/test_etxrd/subsegments.xrds +openid/test/data/test_etxrd/valid-populated-xrds.xml +openid/yadis/__init__.py +openid/yadis/accept.py +openid/yadis/constants.py +openid/yadis/discover.py +openid/yadis/etxrd.py +openid/yadis/filters.py +openid/yadis/manager.py +openid/yadis/parsehtml.py +openid/yadis/services.py +openid/yadis/xri.py +openid/yadis/xrires.py +python3_openid.egg-info/PKG-INFO +python3_openid.egg-info/SOURCES.txt +python3_openid.egg-info/dependency_links.txt +python3_openid.egg-info/requires.txt +python3_openid.egg-info/top_level.txt \ No newline at end of file diff --git a/python3_openid.egg-info/dependency_links.txt b/python3_openid.egg-info/dependency_links.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b137891791fe96927ad78e64b0aad7bded08bdc --- /dev/null +++ b/python3_openid.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/python3_openid.egg-info/requires.txt b/python3_openid.egg-info/requires.txt new file mode 100644 index 0000000000000000000000000000000000000000..36969f2c4b81b8d563bf352a569328e8c5a75a74 --- /dev/null +++ b/python3_openid.egg-info/requires.txt @@ -0,0 +1 @@ +defusedxml diff --git a/python3_openid.egg-info/top_level.txt b/python3_openid.egg-info/top_level.txt new file mode 100644 index 0000000000000000000000000000000000000000..c2f7f6396d52c4c7297a5b2c05879bbba550ae60 --- /dev/null +++ b/python3_openid.egg-info/top_level.txt @@ -0,0 +1 @@ +openid diff --git a/run_tests.sh b/run_tests.sh deleted file mode 100755 index 4ea33c0940b38f5e4bf166e0419295b22ba9dc43..0000000000000000000000000000000000000000 --- a/run_tests.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -# naive version that doesn't run enough tests: -# python openid/test/test*.py - -python3 -m unittest openid.test.test_suite diff --git a/setup.cfg b/setup.cfg index 5706708196be26fd3906d912e2de5e5bcc384a6d..bf52e6a907b11e9a1ae936764188ce3c82ec3e1a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,9 @@ [sdist] -force_manifest=1 -formats=gztar,zip +force_manifest = 1 +formats = gztar,zip + +[egg_info] +tag_build = +tag_svn_revision = 0 +tag_date = 0 + diff --git a/setup.py b/setup.py index 7818cff64bb17ca4adeab74fa7168f082a88e2b6..dcc219cee93babf97dea776e7d10aec45fbdbf18 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ import sys import os -from distutils.core import setup +from setuptools import setup import openid @@ -37,6 +37,9 @@ Includes example code and support for a variety of storage back-ends.''', maintainer_email='rami.chowdhury@gmail.com', download_url=('http://github.com/necaris/python3-openid/tarball' '/v{}'.format(version)), + install_requires=[ + 'defusedxml', + ], classifiers=[ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 0939a81bc1d586a2989b76af08bd9d1a9c30103b..0000000000000000000000000000000000000000 --- a/tox.ini +++ /dev/null @@ -1,14 +0,0 @@ -# Tox (http://tox.testrun.org/) is a tool for running tests -# in multiple virtualenvs. This configuration file will run the -# test suite on all supported python versions. To use it, "pip install tox" -# and then run "tox" from this directory. - -[tox] -envlist = py32, py33 - -[testenv] -commands = ./run_tests.sh -deps = - Django==1.5 - nose - pycrypto