nicolask - thanks very much for the contribution to Mailman! I'm afraid I'm going to have to reject this merge proposal though because I think this issue needs to be solved at a different level. The model tries to be as simple as possible, and because the IUser object is a fundamental object, the IUserManager.create_user() method should not implement these additional semantics. On the mailing list, I outlined an approach that I think would be better.
In the hopes that you'll continue to contribute to Mailman, I'd like to offer some additional style feedback on your diff. Again, thanks for working on Mailman!
Of course, you can get rid of that commented out line, but also, since your
tests all use the IUserManager utility, it might be better to do something
like this in the setUp():
self._user_manager = getUtility(IUserManager)
and then use self._user_manager instead of having to get the utility every
time.
It would be better to use self.assertNotEqual() here, since the error message
is better should the test ever fail. (Also, remember, a single space comes
after commas in an argument list.)
You almost never want to use a bare except. Mailman uses them in just a few
very limited places, and it's almost always to perform some task and then
re-raise the exception. Examples are: log the error and then re-raise, or
abort the transaction and re-raise. In all other cases, you should catch the
appropriate exception explicitly.
Generally, you don't want to raise the base Exception, but instead some more
appropriate specific exception. However, in this particular case, the
IUserManager already implements this logic in its get_address() method, so it
should just call that.
Then you can just add an assertion that the address exists, i.e. is not None.
That will be logically consistent if you were to catch ExistingAddressError
above. E.g.
address = self.get_address(email)
assert address is not None
> + if addresses.one().user == None:
As a general style consideration, we never compare against None using
equality; always use identity to compare against singletons like None. While
the above comments would make most of this code go away, the test should be
rewritten like so:
nicolask - thanks very much for the contribution to Mailman! I'm afraid I'm going to have to reject this merge proposal though because I think this issue needs to be solved at a different level. The model tries to be as simple as possible, and because the IUser object is a fundamental object, the IUserManager. create_ user() method should not implement these additional semantics. On the mailing list, I outlined an approach that I think would be better.
In the hopes that you'll continue to contribute to Mailman, I'd like to offer some additional style feedback on your diff. Again, thanks for working on Mailman!
=== added file 'src/mailman/ model/tests/ test_usermanage r.py' model/tests/ test_usermanage r.py 1970-01-01 00:00:00 +0000 model/tests/ test_usermanage r.py 2013-12-28 10:18:08 +0000 (unittest. TestCase) : IAddress) ('<email address hidden>','No one')
--- src/mailman/
+++ src/mailman/
> +class TestUserManager
> + """Test usermanager."""
> +
> + layer = ConfigLayer
> +
> + def setUp(self):
> + self._mlist = create_list('<email address hidden>')
> + #getUtility(
Of course, you can get rid of that commented out line, but also, since your
tests all use the IUserManager utility, it might be better to do something
like this in the setUp():
and then use self._user_manager instead of having to get the utility every
time.
> + user(self) : IUserManager) .create_ user( user_existing_ address_ user(self) : IUserManager) .create_ user( es(ExistingAddr essError, getUtility( IUserManager) .create_ user,*(
> + def test_create_
> + anne = getUtility(
> + '<email address hidden>', 'Anne Person')
> +
> + def test_create_
> + anne = getUtility(
> + '<email address hidden>', 'Anne Person')
> + self.assertRais
> + '<email address hidden>', 'Anne Person'))
You'll want to make sure this line is less than 80 characters wide. Also, you
should need the * there. I think the following would work better:
> + user_existing_ address_ no_user( self): IUserManager) .create_ user( IUserManager) .create_ user( (anne.user_ id != noone.user_id)
> + def test_create_
> + anne = getUtility(
> + '<email address hidden>', 'Anne Person')
> + noone = getUtility(
> + '<email address hidden>','No one')
> + self.assertTrue
It would be better to use self.assertNotE qual() here, since the error message
is better should the test ever fail. (Also, remember, a single space comes
after commas in an argument list.)
https:/ /docs.python. org/2.7/ library/ unittest. html?highlight= unittest# assert- methods
=== modified file 'src/mailman/ model/usermanag er.py' model/usermanag er.py 2013-01-01 14:05:42 +0000 model/usermanag er.py 2013-12-28 10:18:08 +0000 IUserManager) address( email, display_name) address( email, display_name)
--- src/mailman/
+++ src/mailman/
> @@ -40,13 +40,24 @@
> @implementer(
> class UserManager:
> """See `IUserManager`."""
> -
> - def create_user(self, email=None, display_name=None):
> + @dbconnection
> + def create_user(self, store, email=None, display_name=None):
> """See `IUserManager`."""
> user = User(display_name, Preferences())
> if email:
> - address = self.create_
> + address = None
> + try:
> + address = self.create_
> + except:
You almost never want to use a bare except. Mailman uses them in just a few
very limited places, and it's almost always to perform some task and then
re-raise the exception. Examples are: log the error and then re-raise, or
abort the transaction and re-raise. In all other cases, you should catch the
appropriate exception explicitly.
> + addresses = store.find(Address, email=email. lower() ) "inconsistent results")
> + if addresses.count() == 0:
> + raise Exception(
Generally, you don't want to raise the base Exception, but instead some more
appropriate specific exception. However, in this particular case, the
IUserManager already implements this logic in its get_address() method, so it
should just call that.
Then you can just add an assertion that the address exists, i.e. is not None. Error
That will be logically consistent if you were to catch ExistingAddress
above. E.g.
address = self.get_ address( email)
assert address is not None
> + if addresses. one().user == None:
As a general style consideration, we never compare against None using
equality; always use identity to compare against singletons like None. While
the above comments would make most of this code go away, the test should be
rewritten like so:
if address.one().user is None
> + address = addresses.one() Error(email)
> + else:
> + raise ExistingAddress
> user.link(address)
> + store.add(user)
> return user
>
> @dbconnection