Barry Warsaw pushed to branch master at mailman / Mailman
Commits: 5a6344a8 by Aurélien Bompard at 2016-01-13T19:36:29-05:00 Allow fuzz search for members in SubscriptionService - - - - - bbe2a437 by Aurélien Bompard at 2016-01-13T19:36:29-05:00 Member search can be done using GET requests - - - - - a4ebbd16 by Barry Warsaw at 2016-01-13T19:49:16-05:00 Add NEWS and tweak. - - - - - 6 changed files: - src/mailman/docs/NEWS.rst - src/mailman/interfaces/subscriptions.py - src/mailman/model/docs/subscriptions.rst - src/mailman/model/subscriptions.py - src/mailman/rest/docs/membership.rst - src/mailman/rest/members.py Changes: ===================================== src/mailman/docs/NEWS.rst ===================================== --- a/src/mailman/docs/NEWS.rst +++ b/src/mailman/docs/NEWS.rst @@ -79,6 +79,8 @@ Interfaces same algorithm. (Closes #118) * ``IMessageStore.delete_message()`` no longer raises a ``LookupError`` when you attempt to delete a nonexistent message from the message store. + * ``ISubscriptionService.find_members()`` accepts asterisks as wildcards in + the ``subscriber`` argument string. Given by Aurélien Bompard. Internal API ------------ @@ -133,6 +135,8 @@ REST given action. * Global and list-centric bans can now be managed through the REST API. Given by Aurélien Bompard. + * ``<api>/members/find`` accepts GET query parameters in addition to POST + arguments. Given by Aurélien Bompard. Other ----- ===================================== src/mailman/interfaces/subscriptions.py ===================================== --- a/src/mailman/interfaces/subscriptions.py +++ b/src/mailman/interfaces/subscriptions.py @@ -110,7 +110,8 @@ class ISubscriptionService(Interface): list. :param subscriber: The email address or user id of the user getting - subscribed. + subscribed. This argument may contain asterisks, which will be + interpreted as wildcards in the search pattern. :type subscriber: string or int :param list_id: The list id of the mailing list to search for the subscriber's memberships on. ===================================== src/mailman/model/docs/subscriptions.rst ===================================== --- a/src/mailman/model/docs/subscriptions.rst +++ b/src/mailman/model/docs/subscriptions.rst @@ -105,6 +105,22 @@ There may be no matching memberships. >>> list(service.find_members('d...@example.com')) [] +The address may contain asterisks, which will be interpreted as a wildcard in +the search pattern. + + >>> for member in service.find_members('*person*'): + ... print(member) + <Member: Anne Person <aper...@example.com> + on a...@example.com as MemberRole.member> + <Member: Anne Person <aper...@example.com> + on a...@example.com as MemberRole.owner> + <Member: Bart Person <bper...@example.com> + on a...@example.com as MemberRole.moderator> + <Member: Bart Person <bper...@example.com> + on b...@example.com as MemberRole.owner> + <Member: Cris Person <cper...@example.com> + on c...@example.com as MemberRole.member> + Memberships can also be searched for by user id. >>> for member in service.find_members(anne_1.user.user_id): ===================================== src/mailman/model/subscriptions.py ===================================== --- a/src/mailman/model/subscriptions.py +++ b/src/mailman/model/subscriptions.py @@ -94,10 +94,18 @@ class SubscriptionService: if subscriber is not None: if isinstance(subscriber, str): # subscriber is an email address. - q_address = q_address.filter( - Address.email == subscriber.lower()) - q_user = q_user.join(User.addresses).filter( - Address.email == subscriber.lower()) + subscriber = subscriber.lower() + if '*' in subscriber: + subscriber = subscriber.replace('*', '%') + q_address = q_address.filter( + Address.email.like(subscriber)) + q_user = q_user.join(User.addresses).filter( + Address.email.like(subscriber)) + else: + q_address = q_address.filter( + Address.email == subscriber) + q_user = q_user.join(User.addresses).filter( + Address.email == subscriber) else: # subscriber is a user id. q_address = q_address.join(Address.user).filter( ===================================== src/mailman/rest/docs/membership.rst ===================================== --- a/src/mailman/rest/docs/membership.rst +++ b/src/mailman/rest/docs/membership.rst @@ -626,6 +626,28 @@ Finally, we can search for a specific member given all three criteria. start: 0 total_size: 1 +Search can also be performed using HTTP GET queries. + + >>> dump_json('http://localhost:9001/3.0/members/find' + ... '?subscriber=cper...@example.com' + ... '&list_id=bee.example.com' + ... '&role=member' + ... ) + entry 0: + address: http://localhost:9001/3.0/addresses/cper...@example.com + delivery_mode: regular + email: cper...@example.com + http_etag: ... + list_id: bee.example.com + member_id: 2 + moderation_action: defer + role: member + self_link: http://localhost:9001/3.0/members/2 + user: http://localhost:9001/3.0/users/2 + http_etag: ... + start: 0 + total_size: 1 + Joining a mailing list ====================== ===================================== src/mailman/rest/members.py ===================================== --- a/src/mailman/rest/members.py +++ b/src/mailman/rest/members.py @@ -356,19 +356,32 @@ class _FoundMembers(MemberCollection): class FindMembers(_MemberBase): """/members/find""" + def on_get(self, request, response): + return self._find(request, response) + def on_post(self, request, response): + return self._find(request, response) + + def _find(self, request, response): """Find a member""" service = getUtility(ISubscriptionService) validator = Validator( list_id=str, subscriber=str, role=enum_validator(MemberRole), - _optional=('list_id', 'subscriber', 'role')) + # Allow pagination. + page=int, + count=int, + _optional=('list_id', 'subscriber', 'role', 'page', 'count')) try: data = validator(request) except ValueError as error: bad_request(response, str(error)) else: + # Remove any optional pagination query elements; they will be + # handled later. + data.pop('page', None) + data.pop('count', None) members = service.find_members(**data) resource = _FoundMembers(members, self.api) okay(response, etag(resource._make_collection(request))) View it on GitLab: https://gitlab.com/mailman/mailman/compare/95446742669349777ee4101237a76395f1dfaa87...a4ebbd164bdba4a7ede651dfcf802c300e8e9743
_______________________________________________ Mailman-checkins mailing list Mailman-checkins@python.org Unsubscribe: https://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org