Skip to content

Commit

Permalink
Merge branch 'develop': release 0.12
Browse files Browse the repository at this point in the history
  • Loading branch information
mfogel committed Dec 24, 2014
2 parents 0237772 + 92fb848 commit 002fd0b
Show file tree
Hide file tree
Showing 17 changed files with 218 additions and 102 deletions.
18 changes: 3 additions & 15 deletions .travis.yml
@@ -1,20 +1,8 @@
language: python
python:
- 2.7
- 3.3
env:
- DJANGO='django>=1.5,<1.6'
- DJANGO='django>=1.6,<1.7'
- DJANGO='git+git://github.com/django/django.git@1.7c1'
before_install:
- export PIP_USE_MIRRORS=true
install:
- pip install $DJANGO
- pip install -e .
- pip install coveralls
before_script:
- export DJANGO_SETTINGS_MODULE=simple_email_confirmation.test_project.settings
- pip install tox coveralls
script:
- coverage run --include='*simple_email_confirmation*' --omit='*test_project*,*tests.py' $(which django-admin.py) test simple_email_confirmation
- tox
- tox -e coverage
after_success:
- coveralls
15 changes: 8 additions & 7 deletions README.rst
Expand Up @@ -92,14 +92,15 @@ Installation
Running the Tests
-----------------

Using `Doug Hellman's virtualenvwrapper`__:
#. Install `tox`__.

.. code:: sh
#. From the repository root, run

mktmpenv
pip install django-simple-email-confirmation
export DJANGO_SETTINGS_MODULE=simple_email_confirmation.test_project.settings
django-admin.py test simple_email_confirmation
.. code:: sh
tox
It's that simple.


Found a Bug?
Expand All @@ -118,7 +119,7 @@ __ http://pypi.python.org/pypi/django-simple-email-confirmation/
__ http://www.pip-installer.org/
__ https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
__ https://docs.djangoproject.com/en/dev/topics/auth/customizing/#specifying-a-custom-user-model
__ http://www.doughellmann.com/projects/virtualenvwrapper/
__ https://tox.readthedocs.org/
__ https://github.com/mfogel/django-simple-email-confirmation
__ https://github.com/pinax/django-email-confirmation
__ https://github.com/jtauber/django-email-confirmation
16 changes: 14 additions & 2 deletions setup.py
Expand Up @@ -2,12 +2,14 @@
from os import path
from setuptools import setup


# read() and find_version() taken from jezdez's python apps, ex:
# https://github.com/jezdez/django_compressor/blob/develop/setup.py

def read(*parts):
return open(path.join(path.dirname(__file__), *parts)).read()


def find_version(*file_paths):
version_file = read(*file_paths)
version_match = re.search(
Expand All @@ -17,6 +19,7 @@ def find_version(*file_paths):
return version_match.group(1)
raise RuntimeError("Unable to find version string.")


setup(
name='django-simple-email-confirmation',
version=find_version('simple_email_confirmation', '__init__.py'),
Expand All @@ -29,8 +32,10 @@ def find_version(*file_paths):
packages=[
'simple_email_confirmation',
'simple_email_confirmation.migrations',
'simple_email_confirmation.test_project',
'simple_email_confirmation.test_project.apps.test_app',
'simple_email_confirmation.south_migrations',
'simple_email_confirmation.tests',
'simple_email_confirmation.tests.myproject',
'simple_email_confirmation.tests.myproject.myapp',
],
install_requires=['django>=1.5.0'],
classifiers=[
Expand All @@ -40,6 +45,13 @@ def find_version(*file_paths):
'License :: OSI Approved :: BSD License',
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.2",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
'Topic :: Utilities',
"Framework :: Django",
]
Expand Down
9 changes: 8 additions & 1 deletion simple_email_confirmation/__init__.py
@@ -1,4 +1,11 @@
__version__ = '0.11'
__version__ = '0.12'
__all__ = [
'SimpleEmailConfirmationUserMixin',
'EmailAddress',
'email_confirmed',
'unconfirmed_email_created',
'primary_email_changed',
]

from .models import SimpleEmailConfirmationUserMixin, EmailAddress
from .signals import (
Expand Down
1 change: 1 addition & 0 deletions simple_email_confirmation/admin.py
Expand Up @@ -5,5 +5,6 @@

class EmailAddressAdmin(admin.ModelAdmin):
list_display = ('user', 'email', 'key', 'set_at', 'confirmed_at')
search_fields = ('email', 'key')

admin.site.register((EmailAddress,), EmailAddressAdmin)
3 changes: 3 additions & 0 deletions simple_email_confirmation/exceptions.py
Expand Up @@ -4,11 +4,14 @@
class SimpleEmailConfirmationException(Exception):
pass


class EmailNotConfirmed(SimpleEmailConfirmationException):
pass


class EmailConfirmationExpired(SimpleEmailConfirmationException):
pass


class EmailIsPrimary(SimpleEmailConfirmationException):
pass
86 changes: 34 additions & 52 deletions simple_email_confirmation/migrations/0001_initial.py
@@ -1,53 +1,35 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models

from django.contrib.auth import get_user_model
User = get_user_model()
user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name)
user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name)


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding model 'EmailAddress'
db.create_table(u'simple_email_confirmation_emailaddress', (
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name=u'email_address_set', to=orm[user_orm_label])),
('email', self.gf('django.db.models.fields.EmailField')(max_length=255)),
('key', self.gf('django.db.models.fields.CharField')(unique=True, max_length=40)),
('set_at', self.gf('django.db.models.fields.DateTimeField')()),
('confirmed_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
))
db.send_create_signal(u'simple_email_confirmation', ['EmailAddress'])

# Adding unique constraint on 'EmailAddress', fields ['user', 'email']
db.create_unique(u'simple_email_confirmation_emailaddress', ['user_id', 'email'])


def backwards(self, orm):
# Removing unique constraint on 'EmailAddress', fields ['user', 'email']
db.delete_unique(u'simple_email_confirmation_emailaddress', ['user_id', 'email'])

# Deleting model 'EmailAddress'
db.delete_table(u'simple_email_confirmation_emailaddress')


models = {
u'simple_email_confirmation.emailaddress': {
'Meta': {'unique_together': "((u'user', u'email'),)", 'object_name': 'EmailAddress'},
'confirmed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
'set_at': ('django.db.models.fields.DateTimeField', [], {}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'email_address_set'", 'to': u"orm['%s']" % user_orm_label})
},
user_model_label: {
},
}

complete_apps = ['simple_email_confirmation']
from __future__ import unicode_literals

from django.db import models, migrations
import django.utils.timezone
from django.conf import settings


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='EmailAddress',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('email', models.EmailField(max_length=255)),
('key', models.CharField(unique=True, max_length=40)),
('set_at', models.DateTimeField(default=django.utils.timezone.now, help_text='When the confirmation key expiration was set')),
('confirmed_at', models.DateTimeField(help_text='First time this email was confirmed', null=True, blank=True)),
('user', models.ForeignKey(related_name='email_address_set', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name_plural': 'email addresses',
},
bases=(models.Model,),
),
migrations.AlterUniqueTogether(
name='emailaddress',
unique_together=set([('user', 'email')]),
),
]
29 changes: 21 additions & 8 deletions simple_email_confirmation/models.py
@@ -1,9 +1,12 @@
from __future__ import unicode_literals

from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import models
from django.db.models.signals import post_save
from django.utils.crypto import get_random_string
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _

from .exceptions import (
EmailConfirmationExpired, EmailIsPrimary, EmailNotConfirmed,
Expand Down Expand Up @@ -156,7 +159,7 @@ def generate_key(self):

def create_confirmed(self, email, user=None):
"Create an email address in the confirmed state"
user = user or self.instance
user = user or getattr(self, 'instance', None)
if not user:
raise ValueError('Must specify user or call from related manager')
key = self.generate_key()
Expand All @@ -169,7 +172,7 @@ def create_confirmed(self, email, user=None):

def create_unconfirmed(self, email, user=None):
"Create an email address in the unconfirmed state"
user = user or self.instance
user = user or getattr(self, 'instance', None)
if not user:
raise ValueError('Must specify user or call from related manager')
key = self.generate_key()
Expand Down Expand Up @@ -207,21 +210,22 @@ class EmailAddress(models.Model):
key = models.CharField(max_length=40, unique=True)

set_at = models.DateTimeField(
default=lambda: timezone.now(),
help_text='When the confirmation key expiration was set',
default=timezone.now,
help_text=_('When the confirmation key expiration was set'),
)
confirmed_at = models.DateTimeField(
blank=True, null=True,
help_text='First time this email was confirmed',
help_text=_('First time this email was confirmed'),
)

objects = EmailAddressManager()

class Meta:
unique_together = (('user', 'email'),)
verbose_name_plural = "email addresses"

def __unicode__(self):
return u'{} <{}>'.format(self.user, self.email)
return '{} <{}>'.format(self.user, self.email)

@property
def is_confirmed(self):
Expand Down Expand Up @@ -263,8 +267,17 @@ def reset_confirmation(self):
def auto_add(sender, **kwargs):
if sender == get_user_model() and kwargs['created']:
user = kwargs.get('instance')
email = user.get_primary_email()
user.add_unconfirmed_email(email)
# softly failing on using these methods on `user` to support
# not using the SimpleEmailConfirmationMixin in your User model
# https://github.com/mfogel/django-simple-email-confirmation/pull/3
if hasattr(user, 'get_primary_email'):
email = user.get_primary_email()
else:
email = user.email
if hasattr(user, 'add_unconfirmed_email'):
user.add_unconfirmed_email(email)
else:
user.email_address_set.create_unconfirmed(email)

# TODO: try to only connect this to the User model. We can't use
# get_user_model() here - results in import loop.
Expand Down
54 changes: 54 additions & 0 deletions simple_email_confirmation/south_migrations/0001_initial.py
@@ -0,0 +1,54 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models

from django.contrib.auth import get_user_model
User = get_user_model()
user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name)
user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name)


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding model 'EmailAddress'
db.create_table('simple_email_confirmation_emailaddress', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('user', self.gf('django.db.models.fields.related.ForeignKey')(related_name='email_address_set', to=orm[user_orm_label])),
('email', self.gf('django.db.models.fields.EmailField')(max_length=255)),
('key', self.gf('django.db.models.fields.CharField')(unique=True, max_length=40)),
('set_at', self.gf('django.db.models.fields.DateTimeField')()),
('confirmed_at', self.gf('django.db.models.fields.DateTimeField')(null=True, blank=True)),
))
db.send_create_signal('simple_email_confirmation', ['EmailAddress'])

# Adding unique constraint on 'EmailAddress', fields ['user', 'email']
db.create_unique('simple_email_confirmation_emailaddress', ['user_id', 'email'])


def backwards(self, orm):
# Removing unique constraint on 'EmailAddress', fields ['user', 'email']
db.delete_unique('simple_email_confirmation_emailaddress', ['user_id', 'email'])

# Deleting model 'EmailAddress'
db.delete_table('simple_email_confirmation_emailaddress')


models = {
'simple_email_confirmation.emailaddress': {
'Meta': {'unique_together': "(('user', 'email'),)", 'object_name': 'EmailAddress'},
'confirmed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40'}),
'set_at': ('django.db.models.fields.DateTimeField', [], {}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'email_address_set'", 'to': "orm['%s']" % user_orm_label})
},
user_model_label: {
},
}

complete_apps = ['simple_email_confirmation']
File renamed without changes.
Empty file.
Empty file.

0 comments on commit 002fd0b

Please sign in to comment.