<commit_before>from datetime import datetime

from django.conf import settings
from oauth_tokens.api import ApiAbstractBase, Singleton
from oauth_tokens.models import AccessToken
from tweepy import TweepError as TwitterError
import tweepy

__all__ = ['api_call', 'TwitterError']

TWITTER_CLIENT_ID = getattr(settings, 'OAUTH_TOKENS_TWITTER_CLIENT_ID', None)
TWITTER_CLIENT_SECRET = getattr(settings, 'OAUTH_TOKENS_TWITTER_CLIENT_SECRET', None)

class TwitterApi(ApiAbstractBase):

    __metaclass__ = Singleton

    provider = 'twitter'
    error_class = TwitterError

    def get_consistent_token(self):
        return getattr(settings, 'TWITTER_API_ACCESS_TOKEN', None)

    def get_api(self, **kwargs):
        token = self.get_token(**kwargs)

        delimeter = AccessToken.objects.get_token_class(self.provider).delimeter
        auth = tweepy.OAuthHandler(TWITTER_CLIENT_ID, TWITTER_CLIENT_SECRET)
        auth.set_access_token(**token.split(delimeter))

        return tweepy.API(auth, wait_on_rate_limit=True, retry_count=3, retry_delay=1, retry_errors=set([401, 404, 500, 503]))

    def get_api_response(self, *args, **kwargs):
        return getattr(self.api, self.method)(*args, **kwargs)

    def handle_error_no_active_tokens(self, e, *args, **kwargs):
        if self.used_access_tokens and self.api:

            # check if all tokens are blocked by rate limits response
            try:
                rate_limit_status = self.api.rate_limit_status()
            except self.error_class, e:
                # handle rate limit on rate_limit_status request -> wait 15 min and repeat main request
                if e[0][0]['code'] == 88:
                    self.used_access_tokens = []
                    return self.sleep_repeat_call(seconds=60 * 15, *args, **kwargs)
                else:
                    raise

            # TODO: wrong logic, path is different completelly sometimes
            method = '/%s' % self.method.replace('_', '/')
            status = [methods for methods in rate_limit_status['resources'].values() if method in methods][0][method]
            if status['remaining'] == 0:
                secs = (datetime.fromtimestamp(status['reset']) - datetime.now()).seconds
                self.used_access_tokens = []
                return self.sleep_repeat_call(seconds=secs, *args, **kwargs)
            else:
                return self.repeat_call(*args, **kwargs)
        else:
            return super(TwitterApi, self).handle_error_no_active_tokens(e, *args, **kwargs)

    def handle_error_code(self, e, *args, **kwargs):
        e.code = e[0][0]['code']
        return super(TwitterApi, self).handle_error_code(e, *args, **kwargs)

    def handle_error_code_88(self, e, *args, **kwargs):
        # Rate limit exceeded
        token = AccessToken.objects.get_token_class(self.provider).delimeter.join(
            [self.api.auth.access_token, self.api.auth.access_token_secret])
        self.used_access_tokens += [token]
        return self.repeat_call(*args, **kwargs)

#     def handle_error_code_63(self, e, *args, **kwargs):
# User has been suspended.
#         self.refresh_tokens()
#         return self.repeat_call(*args, **kwargs)

def api_call(*args, **kwargs):
    api = TwitterApi()
    return api.call(*args, **kwargs)
<commit_msg>fixed parameter error<commit_after>from datetime import datetime

from django.conf import settings
from oauth_tokens.api import ApiAbstractBase, Singleton
from oauth_tokens.models import AccessToken
from tweepy import TweepError as TwitterError
import tweepy

__all__ = ['api_call', 'TwitterError']

TWITTER_CLIENT_ID = getattr(settings, 'OAUTH_TOKENS_TWITTER_CLIENT_ID', None)
TWITTER_CLIENT_SECRET = getattr(settings, 'OAUTH_TOKENS_TWITTER_CLIENT_SECRET', None)

class TwitterApi(ApiAbstractBase):

    __metaclass__ = Singleton

    provider = 'twitter'
    error_class = TwitterError

    def get_consistent_token(self):
        return getattr(settings, 'TWITTER_API_ACCESS_TOKEN', None)

    def get_api(self, **kwargs):
        token = self.get_token(**kwargs)

        delimeter = AccessToken.objects.get_token_class(self.provider).delimeter
        auth = tweepy.OAuthHandler(TWITTER_CLIENT_ID, TWITTER_CLIENT_SECRET)
        auth.set_access_token(*token.split(delimeter))

        return tweepy.API(auth, wait_on_rate_limit=True, retry_count=3, retry_delay=1, retry_errors=set([401, 404, 500, 503]))

    def get_api_response(self, *args, **kwargs):
        return getattr(self.api, self.method)(*args, **kwargs)

    def handle_error_no_active_tokens(self, e, *args, **kwargs):
        if self.used_access_tokens and self.api:

            # check if all tokens are blocked by rate limits response
            try:
                rate_limit_status = self.api.rate_limit_status()
            except self.error_class, e:
                # handle rate limit on rate_limit_status request -> wait 15 min and repeat main request
                if e[0][0]['code'] == 88:
                    self.used_access_tokens = []
                    return self.sleep_repeat_call(seconds=60 * 15, *args, **kwargs)
                else:
                    raise

            # TODO: wrong logic, path is different completelly sometimes
            method = '/%s' % self.method.replace('_', '/')
            status = [methods for methods in rate_limit_status['resources'].values() if method in methods][0][method]
            if status['remaining'] == 0:
                secs = (datetime.fromtimestamp(status['reset']) - datetime.now()).seconds
                self.used_access_tokens = []
                return self.sleep_repeat_call(seconds=secs, *args, **kwargs)
            else:
                return self.repeat_call(*args, **kwargs)
        else:
            return super(TwitterApi, self).handle_error_no_active_tokens(e, *args, **kwargs)

    def handle_error_code(self, e, *args, **kwargs):
        e.code = e[0][0]['code']
        return super(TwitterApi, self).handle_error_code(e, *args, **kwargs)

    def handle_error_code_88(self, e, *args, **kwargs):
        # Rate limit exceeded
        token = AccessToken.objects.get_token_class(self.provider).delimeter.join(
            [self.api.auth.access_token, self.api.auth.access_token_secret])
        self.used_access_tokens += [token]
        return self.repeat_call(*args, **kwargs)

#     def handle_error_code_63(self, e, *args, **kwargs):
# User has been suspended.
#         self.refresh_tokens()
#         return self.repeat_call(*args, **kwargs)

def api_call(*args, **kwargs):
    api = TwitterApi()
    return api.call(*args, **kwargs)
<|endoftext|>


<commit_before>"""
    SoftLayer.deprecated
    ~~~~~~~~~~~~~~~~~~~~
    This is where deprecated APIs go for their eternal slumber

    :copyright: (c) 2013, SoftLayer Technologies, Inc. All rights reserved.
    :license: BSD, see LICENSE for more details.
"""
from warnings import warn
from SoftLayer.exceptions import SoftLayerError

class DeprecatedClientMixin():
    """ This mixin is to be used in SoftLayer.Client so all of these methods
        should be available to the client but are all deprecated.
    """

    def __init__(self, id=None, username=None, api_key=None, **kwargs):

        if id is not None:
            warn("The id parameter is deprecated", DeprecationWarning)
            self.set_init_parameter(int(id))

        if username and api_key:
            self.set_authentication(username, api_key)

    def __getattr__(self, name):
        """ Attempt a SoftLayer API call.

        Use this as a catch-all so users can call SoftLayer API methods
        directly against their client object. If the property or method
        relating to their client object doesn't exist then assume the user is
        attempting a SoftLayer API call and return a simple function that makes
        an XML-RPC call.

        :param name: method name

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        if name in ["__name__", "__bases__"]:
            raise AttributeError("'Obj' object has no attribute '%s'" % name)

        def call_handler(*args, **kwargs):
            if self._service_name is None:
                raise SoftLayerError(
                    "Service is not set on Client instance.")
            kwargs['headers'] = self._headers
            return self.call(self._service_name, name, *args, **kwargs)
        return call_handler

    def add_raw_header(self, name, value):
        """ Set HTTP headers for API calls.

        :param name: the header name
        :param value: the header value

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        self._raw_headers[name] = value

    def add_header(self, name, value):
        """ Set a SoftLayer API call header.

        :param name: the header name
        :param value: the header value

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        name = name.strip()
        if name is None or name == '':
            raise SoftLayerError('Please specify a header name.')

        self._headers[name] = value

    def remove_header(self, name):
        """ Remove a SoftLayer API call header.

        :param name: the header name

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        if name in self._headers:
            del self._headers[name.strip()]

    def set_authentication(self, username, api_key):
        """ Set user and key to authenticate a SoftLayer API call.

        Use this method if you wish to bypass the API_USER and API_KEY class
        constants and set custom authentication per API call.

        See https://manage.softlayer.com/Administrative/apiKeychain for more
        information.

        :param username: the username to authenticate with
        :param api_key: the user's API key

        ..  deprecated:: 2.0.0

        """
        self.add_header('authenticate', {
            'username': username.strip(),
            'apiKey': api_key.strip(),
        })

    def set_init_parameter(self, id):
        """ Set an initialization parameter header.

        Initialization parameters instantiate a SoftLayer API service object to
        act upon during your API method call. For instance, if your account has
        a server with ID number 1234, then setting an initialization parameter
        of 1234 in the SoftLayer_Hardware_Server Service instructs the API to
        act on server record 1234 in your method calls.

        See http://sldn.softlayer.com/article/Using-Initialization-Parameters-SoftLayer-API  # NOQA
        for more information.

        :param id: the ID of the SoftLayer API object to instantiate

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        self.add_header(self._service_name + 'InitParameters', {
            'id': int(id)
        })

    def set_object_mask(self, mask):
        """ Set an object mask to a SoftLayer API call.

        Use an object mask to retrieve data related your API call's result.
        Object masks are skeleton objects, or strings that define nested
        relational properties to retrieve along with an object's local
        properties. See
        http://sldn.softlayer.com/article/Using-Object-Masks-SoftLayer-API
        for more information.

        :param mask: the object mask you wish to define

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        header = 'SoftLayer_ObjectMask'

        if isinstance(mask, dict):
            header = '%sObjectMask' % self._service_name

        self.add_header(header, {'mask': mask})

    def set_result_limit(self, limit, offset=0):
        """ Set a result limit on a SoftLayer API call.

        Many SoftLayer API methods return a group of results. These methods
        support a way to limit the number of results retrieved from the
        SoftLayer API in a way akin to an SQL LIMIT statement.

        :param limit: the number of results to limit a SoftLayer API call to
        :param offset: An optional offset at which to begin a SoftLayer API
                       call's returned result

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        self.add_header('resultLimit', {
            'limit': int(limit),
            'offset': int(offset)
        })
<commit_msg>API: Adds deprecation warning to set_authentication()<commit_after>"""
    SoftLayer.deprecated
    ~~~~~~~~~~~~~~~~~~~~
    This is where deprecated APIs go for their eternal slumber

    :copyright: (c) 2013, SoftLayer Technologies, Inc. All rights reserved.
    :license: BSD, see LICENSE for more details.
"""
from warnings import warn
from SoftLayer.exceptions import SoftLayerError

class DeprecatedClientMixin():
    """ This mixin is to be used in SoftLayer.Client so all of these methods
        should be available to the client but are all deprecated.
    """

    def __init__(self, id=None, username=None, api_key=None, **kwargs):

        if id is not None:
            warn("The id parameter is deprecated", DeprecationWarning)
            self.set_init_parameter(int(id))

        if username and api_key:
            self._headers['authenticate'] = {
                'username': username.strip(),
                'apiKey': api_key.strip(),
            }

    def __getattr__(self, name):
        """ Attempt a SoftLayer API call.

        Use this as a catch-all so users can call SoftLayer API methods
        directly against their client object. If the property or method
        relating to their client object doesn't exist then assume the user is
        attempting a SoftLayer API call and return a simple function that makes
        an XML-RPC call.

        :param name: method name

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        if name in ["__name__", "__bases__"]:
            raise AttributeError("'Obj' object has no attribute '%s'" % name)

        def call_handler(*args, **kwargs):
            if self._service_name is None:
                raise SoftLayerError(
                    "Service is not set on Client instance.")
            kwargs['headers'] = self._headers
            return self.call(self._service_name, name, *args, **kwargs)
        return call_handler

    def add_raw_header(self, name, value):
        """ Set HTTP headers for API calls.

        :param name: the header name
        :param value: the header value

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        self._raw_headers[name] = value

    def add_header(self, name, value):
        """ Set a SoftLayer API call header.

        :param name: the header name
        :param value: the header value

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        name = name.strip()
        if name is None or name == '':
            raise SoftLayerError('Please specify a header name.')

        self._headers[name] = value

    def remove_header(self, name):
        """ Remove a SoftLayer API call header.

        :param name: the header name

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        if name in self._headers:
            del self._headers[name.strip()]

    def set_authentication(self, username, api_key):
        """ Set user and key to authenticate a SoftLayer API call.

        Use this method if you wish to bypass the API_USER and API_KEY class
        constants and set custom authentication per API call.

        See https://manage.softlayer.com/Administrative/apiKeychain for more
        information.

        :param username: the username to authenticate with
        :param api_key: the user's API key

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        self.add_header('authenticate', {
            'username': username.strip(),
            'apiKey': api_key.strip(),
        })

    def set_init_parameter(self, id):
        """ Set an initialization parameter header.

        Initialization parameters instantiate a SoftLayer API service object to
        act upon during your API method call. For instance, if your account has
        a server with ID number 1234, then setting an initialization parameter
        of 1234 in the SoftLayer_Hardware_Server Service instructs the API to
        act on server record 1234 in your method calls.

        See http://sldn.softlayer.com/article/Using-Initialization-Parameters-SoftLayer-API  # NOQA
        for more information.

        :param id: the ID of the SoftLayer API object to instantiate

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        self.add_header(self._service_name + 'InitParameters', {
            'id': int(id)
        })

    def set_object_mask(self, mask):
        """ Set an object mask to a SoftLayer API call.

        Use an object mask to retrieve data related your API call's result.
        Object masks are skeleton objects, or strings that define nested
        relational properties to retrieve along with an object's local
        properties. See
        http://sldn.softlayer.com/article/Using-Object-Masks-SoftLayer-API
        for more information.

        :param mask: the object mask you wish to define

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        header = 'SoftLayer_ObjectMask'

        if isinstance(mask, dict):
            header = '%sObjectMask' % self._service_name

        self.add_header(header, {'mask': mask})

    def set_result_limit(self, limit, offset=0):
        """ Set a result limit on a SoftLayer API call.

        Many SoftLayer API methods return a group of results. These methods
        support a way to limit the number of results retrieved from the
        SoftLayer API in a way akin to an SQL LIMIT statement.

        :param limit: the number of results to limit a SoftLayer API call to
        :param offset: An optional offset at which to begin a SoftLayer API
                       call's returned result

        ..  deprecated:: 2.0.0

        """
        warn("deprecated", DeprecationWarning)
        self.add_header('resultLimit', {
            'limit': int(limit),
            'offset': int(offset)
        })
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# © <YEAR(S)> <AUTHOR(S)>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
    "name": "Project Completion Report",
    "summary": "Follow-up project completion (estimated / consumed)",
    "version": "8.0.2.0.0",
    "category": "Project",
    "website": "https://odoo-community.org/",
    "author": "Sebastien Maillard, Elico Corp",
    "license": "AGPL-3",
    "application": False,
    "installable": True,
    "depends": [
        "project_timesheet",
        "project_issue_sheet",
        "project_project_category",
        "business_requirement_deliverable_project",
    ],
    "data": [
        "report/project_completion_report_view.xml",
        "security/ir.model.access.csv",
    ],
}
<commit_msg>Upgrade version number<commit_after># -*- coding: utf-8 -*-
# © <YEAR(S)> <AUTHOR(S)>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
    "name": "Project Completion Report",
    "summary": "Follow-up project completion (estimated / consumed)",
    "version": "8.0.3.0.0",
    "category": "Project",
    "website": "https://odoo-community.org/",
    "author": "Sebastien Maillard, Elico Corp",
    "license": "AGPL-3",
    "application": False,
    "installable": True,
    "depends": [
        "project_timesheet",
        "project_issue_sheet",
        "project_project_category",
        "business_requirement_deliverable_project",
    ],
    "data": [
        "report/project_completion_report_view.xml",
        "security/ir.model.access.csv",
    ],
}
<|endoftext|>


<commit_before>#
# Copyright (c) 2010 rPath, Inc.
#
# All Rights Reserved
#

from django.conf.urls.defaults import *

from mint.django_rest.rbuilder.reporting import imagereports, \
                                                reportdispatcher, \
                                                reports, \
                                                views

from mint.django_rest.rbuilder.inventory import views as inventoryviews
from mint.django_rest.rbuilder.querysets import views as querysetviews
from mint.django_rest.rbuilder.packages import views as packageviews
from mint.django_rest.rbuilder.changelog import views as changelogviews

handler404 = 'mint.django_rest.handler.handler404'
handler500 = 'mint.django_rest.handler.handler500'

urlpatterns = patterns('',
    # Reporting urls
    url(r'^api/reports/(.*?)/descriptor/?$',
        reportdispatcher.ReportDescriptor()),
    url(r'^api/reports/(.*?)/data/(.*?)/?$',
        reportdispatcher.ReportDispatcher()),
    url(r'^api/reports/(.*?)/?$', views.ReportView()),

    #
    # Inventory urls
    #
    url(r'^api/inventory/?$',
        inventoryviews.InventoryService(),
        name='Inventory'),

    # Log
    url(r'^api/inventory/log/?$',
        inventoryviews.InventoryLogService(),
        name='Log'),

    # System States
    url(r'^api/inventory/system_states/?$',
        inventoryviews.InventorySystemStateService(),
        name='SystemStates'),
    url(r'^api/inventory/system_states/(?P<system_state_id>\d+)/?$',
        inventoryviews.InventorySystemStateService(),
        name='SystemState'),

    # Zones
    url(r'^api/inventory/zones/?$',
        inventoryviews.InventoryZoneService(),
        name='Zones'),
    url(r'^api/inventory/zones/(?P<zone_id>\d+)/?$',
        inventoryviews.InventoryZoneService(),
        name='Zone'),

    # Management Nodes
    url(r'^api/inventory/management_nodes/?$',
        inventoryviews.InventoryManagementNodeService(),
        name='ManagementNodes'),
    url(r'^api/inventory/management_nodes/(?P<management_node_id>\d+)/?$',
        inventoryviews.InventoryManagementNodeService(),
        name='ManagementNode'),
    url(r'^api/inventory/zones/(?P<zone_id>\d+)/management_nodes/?$',
        inventoryviews.InventoryZoneManagementNodeService(),
        name='ManagementNodes'),
    url(r'^api/inventory/zones/(?P<zone_id>\d+)/management_nodes/(?P<management_node_id>\d+)/?$',
        inventoryviews.InventoryZoneManagementNodeService(),
        name='ManagementNode'),

    # Management Interfaces
    url(r'^api/inventory/management_interfaces/?$',
        inventoryviews.InventoryManagementInterfaceService(),
        name='ManagementInterfaces'),
    url(r'^api/inventory/management_interfaces/(?P<management_interface_id>\d+)/?$',
        inventoryviews.InventoryManagementInterfaceService(),
        name='ManagementInterface'),

    # System types
    url(r'^api/inventory/system_types/?$',
        inventoryviews.InventorySystemTypeService(),
        name='SystemTypes'),
    url(r'^api/inventory/system_types/(?P<system_type_id>\d+)/?$',
        inventoryviews.InventorySystemTypeService(),
        name='SystemType'),
    url(r'^api/inventory/system_types/(?P<system_type_id>\d+)/systems/?$',
        inventoryviews.InventorySystemTypeSystemsService(),
        name='SystemTypeSystems'),

    # Networks
    url(r'^api/inventory/networks/?$',
        inventoryviews.InventoryNetworkService(),
        name='Networks'),
    url(r'^api/inventory/networks/(?P<network_id>\d+)/?$',
        inventoryviews.InventoryNetworkService(),
        name='Network'),

    # Systems
    url(r'^api/inventory/systems/?$',
        inventoryviews.InventorySystemsService(),
        name='Systems'),
    url(r'^api/inventory/inventory_systems/?$',
        inventoryviews.InventoryInventorySystemsService(),
        name='InventorySystems'),
    url(r'^api/inventory/infrastructure_systems/?$',
        inventoryviews.InventoryInfrastructureSystemsService(),
        name='ImageImportMetadataDescriptor'),
    url(r'^api/inventory/image_import_metadata_descriptor/?$',
        inventoryviews.ImageImportMetadataDescriptorService(),
        name='InfrastructureSystems'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/?$',
        inventoryviews.InventorySystemsSystemService(),
        name='System'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/system_log/?$',
        inventoryviews.InventorySystemsSystemLogService(),
        name='SystemLog'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/jobs/?$',
        inventoryviews.InventorySystemJobsService(),
        name='SystemJobs'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/jobs/(?P<job_id>[a-zA-Z0-9]+)/?$',
        inventoryviews.InventorySystemJobsService(),
        name='SystemJob'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/job_states/(?P<job_state_id>[a-zA-Z0-9]+)/jobs/?$',
        inventoryviews.InventorySystemJobStatesService(),
        name='SystemJobStateJobs'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/system_events/?$',
        inventoryviews.InventorySystemsSystemEventService(),
        name='SystemsSystemEvent'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/system_log/(?P<format>[a-zA-Z]+)/?$',
        inventoryviews.InventorySystemsSystemLogService(),
        name='SystemLogFormat'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/installed_software/?$',
        inventoryviews.InventorySystemsInstalledSoftwareService(),
        name='InstalledSoftware'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/credentials/?$',
        inventoryviews.InventorySystemCredentialsServices(),
        name='SystemCredentials'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/configuration/?$',
        inventoryviews.InventorySystemConfigurationServices(),
        name='SystemConfiguration'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/configuration_descriptor/?$',
        inventoryviews.InventorySystemConfigurationDescriptorServices(),
        name='SystemConfigurationDescriptor'),

    # System Events
    url(r'^api/inventory/system_events/?$',
        inventoryviews.InventorySystemEventsService(),
        name='SystemEvents'),
    url(r'^api/inventory/system_events/(?P<system_event_id>\d+)/?$',
        inventoryviews.InventorySystemEventsService(),
        name='SystemEvent'),

    # System Tags
    url(r'^api/inventory/systems/(?P<system_id>\d+)/system_tags/?$',
        inventoryviews.InventorySystemTagsService(),
        name='SystemTags'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/system_tags/(?P<system_tag_id>\d+)/?$',
        inventoryviews.InventorySystemTagsService(),
        name='SystemTag'),

    # Event Types
    url(r'^api/inventory/event_types/?$',
        inventoryviews.InventoryEventTypesService(),
        name='EventTypes'),
    url(r'^api/inventory/event_types/(?P<event_type_id>\d+)/?$',
        inventoryviews.InventoryEventTypesService(),
        name='EventType'),

    # Users
    url(r'^api/inventory/users/([a-zA-Z0-9]+)/?$',
        inventoryviews.InventoryUsersService(),
        name='Users'),

    # Jobs
    url(r'^api/inventory/jobs/?$',
        inventoryviews.InventoryJobsService(),
        name='Jobs'),
    url(r'^api/inventory/jobs/(?P<job_id>[a-zA-Z0-9]+)/?$',
        inventoryviews.InventoryJobsService(),
        name='Job'),

    # Job States
    url(r'^api/inventory/job_states/?$',
        inventoryviews.InventoryJobStatesService(),
        name='JobStates'),
    url(r'^api/inventory/job_states/(?P<job_state_id>[a-zA-Z0-9]+)/?$',
        inventoryviews.InventoryJobStatesService(),
        name='JobState'),
    url(r'^api/inventory/job_states/(?P<job_state_id>[a-zA-Z0-9]+)/jobs/?$',
        inventoryviews.InventoryJobStatesJobsService(),
        name='JobStateJobs'),

    # Major Versions
    url(r'^api/products/(\w|\-)*/versions/(\w|\.)*/?$',
        inventoryviews.MajorVersionService(),
        name='MajorVersions'),

    # Stages
    url(r'^api/products/(\w|\-)*/versions/(\w|\.)*/stages/(\w)*/?$',
        inventoryviews.StageService(),
        name='Stages'),

    # Projects
    url(r'^api/products/(\w|\-)*/?$',
        inventoryviews.ApplianceService(),
        name='Projects'),

    # Query Sets
    url(r'^api/query_sets/?$',
        querysetviews.QuerySetService(),
        name='QuerySets'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/?$',
        querysetviews.QuerySetService(),
        name='QuerySet'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/all/?$',
        querysetviews.QuerySetAllResultService(),
        name='QuerySetAllResult'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/chosen/?$',
        querysetviews.QuerySetChosenResultService(),
        name='QuerySetChosenResult'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/filtered/?$',
        querysetviews.QuerySetFilteredResultService(),
        name='QuerySetFilteredResult'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/child/?$',
        querysetviews.QuerySetChildResultService(),
        name='QuerySetChildResult'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/filter_descriptor/?$',
        querysetviews.QuerySetFilterDescriptorService(),
        name='QuerySetFilterDescriptor'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/query_tags/?$',
        querysetviews.QueryTagService(),
        name='QueryTags'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/query_tags/(?P<query_tag_id>\d+)/?$',
        querysetviews.QueryTagService(),
        name='QueryTag'),

    # Change Logs
    url(r'^api/changelogs/?$',
        changelogviews.ChangeLogService(),
        name='ChangeLogs'),
    url(r'^api/changelogs/(?P<change_log_id>\d+)/?$',
        changelogviews.ChangeLogService(),
        name='ChangeLog'),

    # Packages
    url(r'^api/packages/?$',
        packageviews.PackageService(),
        name='Packages'),
    url(r'^api/packages/(?P<package_id>\d+)/?$',
        packageviews.PackageService(),
        name='Package'),

    # Package Versions
    url(r'^api/package_versions/?$',
        packageviews.PackageVersionService(),
        name='PackageVersions'),

    url(r'^api/package/(?P<package_id>\d+)/package_versions/?$',
        packageviews.PackagePackageVersionService(),
        name='PackageVersions'),

    url(r'^api/packages/(?P<package_id>\d+)/package_versions/(?P<package_version_id>\d+)/?$',
        packageviews.PackagePackageVersionService(),
        name='PackageVersion'),

    url(r'^api/packages/(?P<package_id>\d+)/package_versions/(?P<package_version_id>\d+)/'
         'package_version_jobs/?$'
        packageviews.PackagePackageVersionJobsService(),
        name='PackageVersionJobs'),

)

<commit_msg>fix url<commit_after>#
# Copyright (c) 2010 rPath, Inc.
#
# All Rights Reserved
#

from django.conf.urls.defaults import *

from mint.django_rest.rbuilder.reporting import imagereports, \
                                                reportdispatcher, \
                                                reports, \
                                                views

from mint.django_rest.rbuilder.inventory import views as inventoryviews
from mint.django_rest.rbuilder.querysets import views as querysetviews
from mint.django_rest.rbuilder.packages import views as packageviews
from mint.django_rest.rbuilder.changelog import views as changelogviews

handler404 = 'mint.django_rest.handler.handler404'
handler500 = 'mint.django_rest.handler.handler500'

urlpatterns = patterns('',
    # Reporting urls
    url(r'^api/reports/(.*?)/descriptor/?$',
        reportdispatcher.ReportDescriptor()),
    url(r'^api/reports/(.*?)/data/(.*?)/?$',
        reportdispatcher.ReportDispatcher()),
    url(r'^api/reports/(.*?)/?$', views.ReportView()),

    #
    # Inventory urls
    #
    url(r'^api/inventory/?$',
        inventoryviews.InventoryService(),
        name='Inventory'),

    # Log
    url(r'^api/inventory/log/?$',
        inventoryviews.InventoryLogService(),
        name='Log'),

    # System States
    url(r'^api/inventory/system_states/?$',
        inventoryviews.InventorySystemStateService(),
        name='SystemStates'),
    url(r'^api/inventory/system_states/(?P<system_state_id>\d+)/?$',
        inventoryviews.InventorySystemStateService(),
        name='SystemState'),

    # Zones
    url(r'^api/inventory/zones/?$',
        inventoryviews.InventoryZoneService(),
        name='Zones'),
    url(r'^api/inventory/zones/(?P<zone_id>\d+)/?$',
        inventoryviews.InventoryZoneService(),
        name='Zone'),

    # Management Nodes
    url(r'^api/inventory/management_nodes/?$',
        inventoryviews.InventoryManagementNodeService(),
        name='ManagementNodes'),
    url(r'^api/inventory/management_nodes/(?P<management_node_id>\d+)/?$',
        inventoryviews.InventoryManagementNodeService(),
        name='ManagementNode'),
    url(r'^api/inventory/zones/(?P<zone_id>\d+)/management_nodes/?$',
        inventoryviews.InventoryZoneManagementNodeService(),
        name='ManagementNodes'),
    url(r'^api/inventory/zones/(?P<zone_id>\d+)/management_nodes/(?P<management_node_id>\d+)/?$',
        inventoryviews.InventoryZoneManagementNodeService(),
        name='ManagementNode'),

    # Management Interfaces
    url(r'^api/inventory/management_interfaces/?$',
        inventoryviews.InventoryManagementInterfaceService(),
        name='ManagementInterfaces'),
    url(r'^api/inventory/management_interfaces/(?P<management_interface_id>\d+)/?$',
        inventoryviews.InventoryManagementInterfaceService(),
        name='ManagementInterface'),

    # System types
    url(r'^api/inventory/system_types/?$',
        inventoryviews.InventorySystemTypeService(),
        name='SystemTypes'),
    url(r'^api/inventory/system_types/(?P<system_type_id>\d+)/?$',
        inventoryviews.InventorySystemTypeService(),
        name='SystemType'),
    url(r'^api/inventory/system_types/(?P<system_type_id>\d+)/systems/?$',
        inventoryviews.InventorySystemTypeSystemsService(),
        name='SystemTypeSystems'),

    # Networks
    url(r'^api/inventory/networks/?$',
        inventoryviews.InventoryNetworkService(),
        name='Networks'),
    url(r'^api/inventory/networks/(?P<network_id>\d+)/?$',
        inventoryviews.InventoryNetworkService(),
        name='Network'),

    # Systems
    url(r'^api/inventory/systems/?$',
        inventoryviews.InventorySystemsService(),
        name='Systems'),
    url(r'^api/inventory/inventory_systems/?$',
        inventoryviews.InventoryInventorySystemsService(),
        name='InventorySystems'),
    url(r'^api/inventory/infrastructure_systems/?$',
        inventoryviews.InventoryInfrastructureSystemsService(),
        name='ImageImportMetadataDescriptor'),
    url(r'^api/inventory/image_import_metadata_descriptor/?$',
        inventoryviews.ImageImportMetadataDescriptorService(),
        name='InfrastructureSystems'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/?$',
        inventoryviews.InventorySystemsSystemService(),
        name='System'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/system_log/?$',
        inventoryviews.InventorySystemsSystemLogService(),
        name='SystemLog'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/jobs/?$',
        inventoryviews.InventorySystemJobsService(),
        name='SystemJobs'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/jobs/(?P<job_id>[a-zA-Z0-9]+)/?$',
        inventoryviews.InventorySystemJobsService(),
        name='SystemJob'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/job_states/(?P<job_state_id>[a-zA-Z0-9]+)/jobs/?$',
        inventoryviews.InventorySystemJobStatesService(),
        name='SystemJobStateJobs'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/system_events/?$',
        inventoryviews.InventorySystemsSystemEventService(),
        name='SystemsSystemEvent'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/system_log/(?P<format>[a-zA-Z]+)/?$',
        inventoryviews.InventorySystemsSystemLogService(),
        name='SystemLogFormat'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/installed_software/?$',
        inventoryviews.InventorySystemsInstalledSoftwareService(),
        name='InstalledSoftware'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/credentials/?$',
        inventoryviews.InventorySystemCredentialsServices(),
        name='SystemCredentials'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/configuration/?$',
        inventoryviews.InventorySystemConfigurationServices(),
        name='SystemConfiguration'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/configuration_descriptor/?$',
        inventoryviews.InventorySystemConfigurationDescriptorServices(),
        name='SystemConfigurationDescriptor'),

    # System Events
    url(r'^api/inventory/system_events/?$',
        inventoryviews.InventorySystemEventsService(),
        name='SystemEvents'),
    url(r'^api/inventory/system_events/(?P<system_event_id>\d+)/?$',
        inventoryviews.InventorySystemEventsService(),
        name='SystemEvent'),

    # System Tags
    url(r'^api/inventory/systems/(?P<system_id>\d+)/system_tags/?$',
        inventoryviews.InventorySystemTagsService(),
        name='SystemTags'),
    url(r'^api/inventory/systems/(?P<system_id>\d+)/system_tags/(?P<system_tag_id>\d+)/?$',
        inventoryviews.InventorySystemTagsService(),
        name='SystemTag'),

    # Event Types
    url(r'^api/inventory/event_types/?$',
        inventoryviews.InventoryEventTypesService(),
        name='EventTypes'),
    url(r'^api/inventory/event_types/(?P<event_type_id>\d+)/?$',
        inventoryviews.InventoryEventTypesService(),
        name='EventType'),

    # Users
    url(r'^api/inventory/users/([a-zA-Z0-9]+)/?$',
        inventoryviews.InventoryUsersService(),
        name='Users'),

    # Jobs
    url(r'^api/inventory/jobs/?$',
        inventoryviews.InventoryJobsService(),
        name='Jobs'),
    url(r'^api/inventory/jobs/(?P<job_id>[a-zA-Z0-9]+)/?$',
        inventoryviews.InventoryJobsService(),
        name='Job'),

    # Job States
    url(r'^api/inventory/job_states/?$',
        inventoryviews.InventoryJobStatesService(),
        name='JobStates'),
    url(r'^api/inventory/job_states/(?P<job_state_id>[a-zA-Z0-9]+)/?$',
        inventoryviews.InventoryJobStatesService(),
        name='JobState'),
    url(r'^api/inventory/job_states/(?P<job_state_id>[a-zA-Z0-9]+)/jobs/?$',
        inventoryviews.InventoryJobStatesJobsService(),
        name='JobStateJobs'),

    # Major Versions
    url(r'^api/products/(\w|\-)*/versions/(\w|\.)*/?$',
        inventoryviews.MajorVersionService(),
        name='MajorVersions'),

    # Stages
    url(r'^api/products/(\w|\-)*/versions/(\w|\.)*/stages/(\w)*/?$',
        inventoryviews.StageService(),
        name='Stages'),

    # Projects
    url(r'^api/products/(\w|\-)*/?$',
        inventoryviews.ApplianceService(),
        name='Projects'),

    # Query Sets
    url(r'^api/query_sets/?$',
        querysetviews.QuerySetService(),
        name='QuerySets'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/?$',
        querysetviews.QuerySetService(),
        name='QuerySet'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/all/?$',
        querysetviews.QuerySetAllResultService(),
        name='QuerySetAllResult'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/chosen/?$',
        querysetviews.QuerySetChosenResultService(),
        name='QuerySetChosenResult'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/filtered/?$',
        querysetviews.QuerySetFilteredResultService(),
        name='QuerySetFilteredResult'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/child/?$',
        querysetviews.QuerySetChildResultService(),
        name='QuerySetChildResult'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/filter_descriptor/?$',
        querysetviews.QuerySetFilterDescriptorService(),
        name='QuerySetFilterDescriptor'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/query_tags/?$',
        querysetviews.QueryTagService(),
        name='QueryTags'),
    url(r'^api/query_sets/(?P<query_set_id>\d+)/query_tags/(?P<query_tag_id>\d+)/?$',
        querysetviews.QueryTagService(),
        name='QueryTag'),

    # Change Logs
    url(r'^api/changelogs/?$',
        changelogviews.ChangeLogService(),
        name='ChangeLogs'),
    url(r'^api/changelogs/(?P<change_log_id>\d+)/?$',
        changelogviews.ChangeLogService(),
        name='ChangeLog'),

    # Packages
    url(r'^api/packages/?$',
        packageviews.PackageService(),
        name='Packages'),
    url(r'^api/packages/(?P<package_id>\d+)/?$',
        packageviews.PackageService(),
        name='Package'),

    # Package Versions
    url(r'^api/package_versions/?$',
        packageviews.PackageVersionService(),
        name='PackageVersions'),

    url(r'^api/package/(?P<package_id>\d+)/package_versions/?$',
        packageviews.PackagePackageVersionService(),
        name='PackageVersions'),

    url(r'^api/packages/(?P<package_id>\d+)/package_versions/(?P<package_version_id>\d+)/?$',
        packageviews.PackagePackageVersionService(),
        name='PackageVersion'),

    url(r'^api/package_versions/(?P<package_version_id>\d+)/package_version_jobs/?$',
        packageviews.PackageVersionJobsService(),
        name='PackageVersionJobs'),

)

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# Copyright (c) 2018 NORDUnet A/S
# All rights reserved.
#
#   Redistribution and use in source and binary forms, with or
#   without modification, are permitted provided that the following
#   conditions are met:
#
#     1. Redistributions of source code must retain the above copyright
#        notice, this list of conditions and the following disclaimer.
#     2. Redistributions in binary form must reproduce the above
#        copyright notice, this list of conditions and the following
#        disclaimer in the documentation and/or other materials provided
#        with the distribution.
#     3. Neither the name of the NORDUnet nor the names of its
#        contributors may be used to endorse or promote products derived
#        from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#

from uuid import uuid4
import time
import requests

from flask import current_app, request, abort, url_for, render_template
from flask_babel import gettext as _

from eduid_userdb import MailAddress
from eduid_userdb.signup import SignupUser
from eduid_userdb.proofing import EmailProofingElement
from eduid_webapp.signup.helpers import generate_eppn

def verify_recaptcha(secret_key, captcha_response, user_ip, retries=3):
    """
    :param secret_key: Recaptcha secret key
    :param captcha_response: User recaptcha response
    :param user_ip: User ip address
    :param retries: Number of times to retry sending recaptcha response

    :type secret_key: str
    :type captcha_response: str
    :type user_ip: str
    :type retries: int

    :return: True|False
    :rtype: bool
    """
    url = 'https://www.google.com/recaptcha/api/siteverify'
    params = {
        'secret': secret_key,
        'response': captcha_response,
        'remoteip': user_ip
    }
    while retries:
        retries -= 1
        try:
            current_app.logger.debug('Sending the CAPTCHA response')
            verify_rs = requests.get(url, params=params, verify=True)
            current_app.logger.debug("CAPTCHA response: {}".format(verify_rs))
            verify_rs = verify_rs.json()
            if verify_rs.get('success', False) is True:
                return True
        except requests.exceptions.RequestException as e:
            if not retries:
                current_app.logger.error('Caught RequestException while '
                                         'sending CAPTCHA, giving up.')
                raise e
            current_app.logger.warning('Caught RequestException while '
                                       'sending CAPTCHA, trying again.')
            current_app.logger.warning(e)
            time.sleep(0.5)

    current_app.logger.info("Invalid CAPTCHA response from {}: {}".format(
        user_ip, verify_rs.get('error-codes', 'Unspecified error')))
    return False

def generate_verification_link():
    code = str(uuid4())
    link = url_for('signup.verify_link', code=code)
    return (link, code)

def send_verification_mail(email):
    (verification_link, code) = generate_verification_link()

    context = {
        "email": email,
        "verification_link": verification_link,
        "site_name": current_app.config.get("EDUID_SITE_NAME"),
        "site_url": current_app.config.get("EDUID_SITE_URL"),
    }

    text = render_template(
            "verification_email.txt.jinja2",
            **context
    )
    html = render_template(
            "verification_email.html.jinja2",
            **context
    )

    signup_user = current_app.private_userdb.get_user_by_pending_mail_address(email)
    if not signup_user:
        mailaddress = EmailProofingElement(email = email, application = 'signup', verified = False,
                                           verification_code = code)
        signup_user = SignupUser(eppn = generate_eppn())
        signup_user.pending_mail_address = mailaddress
        current_app.private_userdb.save(signup_user)
        current_app.logger.info("New user {!s}/{!s} created. e-mail is pending confirmation.".format(signup_user, email))
    else:
        # update mailaddress on existing user with new code
        signup_user.pending_mail_address.verification_code = code
        current_app.private_userdb.save(signup_user)
        current_app.logger.info("User {!s}/{!s} updated with new e-mail confirmation code".format(signup_user, email))

    subject = _("eduid-signup verification email"),
    if current_app.config.get("DEVELOPMENT", False):
        # Development
        current_app.logger.debug("Confirmation e-mail:\nTo: {!s}\nSubject: {!s}\n\n{!s}".format(email, subject, text))
    else:
        current_app.mail_relay.sendmail(subject, [email], text, html)
        current_app.logger.info("Sent email address verification mail to user "
                                "{} about address {!s}.".format(user, email))

class AlreadyVerifiedException(Exception):
    pass

class CodeDoesNotExist(Exception):
    pass

def verify_email_code(code):
    """
    Look up a user in the signup userdb using an e-mail verification code.

    Mark the e-mail address as confirmed, save the user and return the user object.

    :param code: Code as received from user
    :type code: str | unicode

    :return: Signup user object
    :rtype: SignupUser
    """
    signup_db = current_app.private_userdb
    signup_user = signup_db.get_user_by_mail_verification_code(code)

    if not signup_user:
        current_app.logger.debug("Code {!r} not found in database".format(code))
        raise CodeDoesNotExist()

    mail_dict = signup_user.pending_mail_address.to_dict()
    mail_address = MailAddress(data=mail_dict, raise_on_unknown=False)
    if mail_address.is_verified:
        # There really should be no way to get here, is_verified is set to False when
        # the EmailProofingElement is created.
        current_app.logger.debug("Code {!r} already verified "
                                 "({!s})".format(code, mail_address))
        raise AlreadyVerifiedException()

    mail_address.is_verified = True
    mail_address.verified_ts = True
    mail_address.verified_by = 'signup'
    mail_address.is_primary = True
    signup_user.pending_mail_address = None
    signup_user.mail_addresses.add(mail_address)
    result = signup_db.save(signup_user)

    current_app.logger.debug("Code {!r} verified and user {!s} "
                             "saved: {!r}".format(code, signup_user, result))
    return signup_user
<commit_msg>correct verification link<commit_after># -*- coding: utf-8 -*-
#
# Copyright (c) 2018 NORDUnet A/S
# All rights reserved.
#
#   Redistribution and use in source and binary forms, with or
#   without modification, are permitted provided that the following
#   conditions are met:
#
#     1. Redistributions of source code must retain the above copyright
#        notice, this list of conditions and the following disclaimer.
#     2. Redistributions in binary form must reproduce the above
#        copyright notice, this list of conditions and the following
#        disclaimer in the documentation and/or other materials provided
#        with the distribution.
#     3. Neither the name of the NORDUnet nor the names of its
#        contributors may be used to endorse or promote products derived
#        from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#

from uuid import uuid4
import time
import requests

from flask import current_app, request, abort, url_for, render_template
from flask_babel import gettext as _

from eduid_userdb import MailAddress
from eduid_userdb.signup import SignupUser
from eduid_userdb.proofing import EmailProofingElement
from eduid_webapp.signup.helpers import generate_eppn

def verify_recaptcha(secret_key, captcha_response, user_ip, retries=3):
    """
    :param secret_key: Recaptcha secret key
    :param captcha_response: User recaptcha response
    :param user_ip: User ip address
    :param retries: Number of times to retry sending recaptcha response

    :type secret_key: str
    :type captcha_response: str
    :type user_ip: str
    :type retries: int

    :return: True|False
    :rtype: bool
    """
    url = 'https://www.google.com/recaptcha/api/siteverify'
    params = {
        'secret': secret_key,
        'response': captcha_response,
        'remoteip': user_ip
    }
    while retries:
        retries -= 1
        try:
            current_app.logger.debug('Sending the CAPTCHA response')
            verify_rs = requests.get(url, params=params, verify=True)
            current_app.logger.debug("CAPTCHA response: {}".format(verify_rs))
            verify_rs = verify_rs.json()
            if verify_rs.get('success', False) is True:
                return True
        except requests.exceptions.RequestException as e:
            if not retries:
                current_app.logger.error('Caught RequestException while '
                                         'sending CAPTCHA, giving up.')
                raise e
            current_app.logger.warning('Caught RequestException while '
                                       'sending CAPTCHA, trying again.')
            current_app.logger.warning(e)
            time.sleep(0.5)

    current_app.logger.info("Invalid CAPTCHA response from {}: {}".format(
        user_ip, verify_rs.get('error-codes', 'Unspecified error')))
    return False

def generate_verification_link():
    code = str(uuid4())
    link = '{}code/{}'.format(current_app.config['SIGNUP_URL'], code)
    return (link, code)

def send_verification_mail(email):
    (verification_link, code) = generate_verification_link()

    context = {
        "email": email,
        "verification_link": verification_link,
        "site_name": current_app.config.get("EDUID_SITE_NAME"),
        "site_url": current_app.config.get("EDUID_SITE_URL"),
    }

    text = render_template(
            "verification_email.txt.jinja2",
            **context
    )
    html = render_template(
            "verification_email.html.jinja2",
            **context
    )

    signup_user = current_app.private_userdb.get_user_by_pending_mail_address(email)
    if not signup_user:
        mailaddress = EmailProofingElement(email = email, application = 'signup', verified = False,
                                           verification_code = code)
        signup_user = SignupUser(eppn = generate_eppn())
        signup_user.pending_mail_address = mailaddress
        current_app.private_userdb.save(signup_user)
        current_app.logger.info("New user {!s}/{!s} created. e-mail is pending confirmation.".format(signup_user, email))
    else:
        # update mailaddress on existing user with new code
        signup_user.pending_mail_address.verification_code = code
        current_app.private_userdb.save(signup_user)
        current_app.logger.info("User {!s}/{!s} updated with new e-mail confirmation code".format(signup_user, email))

    subject = _("eduid-signup verification email"),
    if current_app.config.get("DEVELOPMENT", False):
        # Development
        current_app.logger.debug("Confirmation e-mail:\nTo: {!s}\nSubject: {!s}\n\n{!s}".format(email, subject, text))
    else:
        current_app.mail_relay.sendmail(subject, [email], text, html)
        current_app.logger.info("Sent email address verification mail to user "
                                "{} about address {!s}.".format(user, email))

class AlreadyVerifiedException(Exception):
    pass

class CodeDoesNotExist(Exception):
    pass

def verify_email_code(code):
    """
    Look up a user in the signup userdb using an e-mail verification code.

    Mark the e-mail address as confirmed, save the user and return the user object.

    :param code: Code as received from user
    :type code: str | unicode

    :return: Signup user object
    :rtype: SignupUser
    """
    signup_db = current_app.private_userdb
    signup_user = signup_db.get_user_by_mail_verification_code(code)

    if not signup_user:
        current_app.logger.debug("Code {!r} not found in database".format(code))
        raise CodeDoesNotExist()

    mail_dict = signup_user.pending_mail_address.to_dict()
    mail_address = MailAddress(data=mail_dict, raise_on_unknown=False)
    if mail_address.is_verified:
        # There really should be no way to get here, is_verified is set to False when
        # the EmailProofingElement is created.
        current_app.logger.debug("Code {!r} already verified "
                                 "({!s})".format(code, mail_address))
        raise AlreadyVerifiedException()

    mail_address.is_verified = True
    mail_address.verified_ts = True
    mail_address.verified_by = 'signup'
    mail_address.is_primary = True
    signup_user.pending_mail_address = None
    signup_user.mail_addresses.add(mail_address)
    result = signup_db.save(signup_user)

    current_app.logger.debug("Code {!r} verified and user {!s} "
                             "saved: {!r}".format(code, signup_user, result))
    return signup_user
<|endoftext|>


<commit_before>#!/usr/bin/env python
# Copyright (c) 2015, Ecole Polytechnique Federale de Lausanne, Blue Brain Project
# All rights reserved.
#
# This file is part of NeuroM <https://github.com/BlueBrain/NeuroM>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     1. Redistributions of source code must retain the above copyright
#        notice, this list of conditions and the following disclaimer.
#     2. Redistributions in binary form must reproduce the above copyright
#        notice, this list of conditions and the following disclaimer in the
#        documentation and/or other materials provided with the distribution.
#     3. Neither the name of the copyright holder nor the names of
#        its contributors may be used to endorse or promote products
#        derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

'''Simple Histogram function for multiple neurons
'''
import numpy as np
from neurom.view import common
from itertools import chain

def histogram(neurons, feature, new_fig=True, subplot=False, **kwargs):
    '''
    Plot a histogram of the selected feature for the population of neurons.
    Plots x-axis versus y-axis on a scatter|histogram|binned values plot.

    More information about the plot and how it works.

    Parameters
    ----------
    neurons : list
        List of Neurons. Single neurons must be encapsulated in a list.

    feature : str
    The feature of interest.

    Options
    -------
    bins : int
    Number of bins for the histogram.

    cumulative : bool
    Sets cumulative histogram on.

    subplot : bool
        Default is False, which returns a matplotlib figure object. If True,
        returns a matplotlib axis object, for use as a subplot.

    Returns
    -------
    figure_output : list
        [fig|ax, figdata, figtext]
        The first item is either a figure object (if subplot is False) or an
        axis object. The second item is an object containing the data used to
        generate the figure. The final item is text used in report generation
        as a figure legend. This text needs to be manually entered in each
        figure file.
    '''

    bins = kwargs.get('bins', 100)
    cumulative = kwargs.get('cumulative', False)

    fig, ax = common.get_figure(new_fig=new_fig, subplot=subplot)

    kwargs['xlabel'] = kwargs.get('xlabel', feature)

    kwargs['ylabel'] = kwargs.get('ylabel', feature + ' fraction')

    kwargs['title'] = kwargs.get('title', feature + ' histogram')

    feature_values = [getattr(neu, 'get_' + feature)() for neu in neurons]

    neu_labels = ['neuron_id' for neu in neurons]

    ax.hist(feature_values, bins=bins, cumulative=cumulative, label=neu_labels)

    kwargs['no_legend'] = len(neu_labels) == 1

    return common.plot_style(fig=fig, ax=ax, **kwargs)

def population_histogram( pops, feature, new_fig=True, normed=False, subplot=False, **kwargs):
    '''
    Plot a histogram of the selected feature for the population of neurons.
    Plots x-axis versus y-axis on a scatter|histogram|binned values plot.

    More information about the plot and how it works.

    Parameters

        populations : populations list

        feature : str
        The feature of interest.

    Options

        bins : int
        Number of bins for the histogram.

        cumulative : bool
        Sets cumulative histogram on.

        subplot : bool
            Default is False, which returns a matplotlib figure object. If True,
            returns a matplotlib axis object, for use as a subplot.

    Returns

        figure_output : list
            [fig|ax, figdata, figtext]
            The first item is either a figure object (if subplot is False) or an
            axis object. The second item is an object containing the data used to
            generate the figure. The final item is text used in report generation
            as a figure legend. This text needs to be manually entered in each
            figure file.
    '''

    bins = kwargs.get('bins', 25)
    cumulative = kwargs.get('cumulative', False)

    fig, ax = common.get_figure(new_fig=new_fig, subplot=subplot)

    kwargs['xlabel'] = kwargs.get('xlabel', feature)

    kwargs['ylabel'] = kwargs.get('ylabel', feature + ' fraction')

    kwargs['title'] = kwargs.get('title', feature + ' histogram')

    multiple_feature_values = []

    for pop in pops:

        feature_values = [getattr(neu, 'get_' + feature)() for neu in pop.neurons]

        # ugly hack to chain in case of list of lists
        if any([isinstance(p, (list, np.ndarray)) for p in feature_values]):

            feature_values = list(chain(*feature_values))

        if normed:

            feature_vals /=

        multiple_feature_values.append(feature_values)

    pops_labels = [pop.name for pop in pops]

    ax.hist(multiple_feature_values, bins=bins, cumulative=cumulative, label=pops_labels)

    kwargs['no_legend'] = len(pops_labels) == 1

    return common.plot_style(fig=fig, ax=ax, **kwargs)<commit_msg>population(s) feature histogram added<commit_after>#!/usr/bin/env python
# Copyright (c) 2015, Ecole Polytechnique Federale de Lausanne, Blue Brain Project
# All rights reserved.
#
# This file is part of NeuroM <https://github.com/BlueBrain/NeuroM>
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     1. Redistributions of source code must retain the above copyright
#        notice, this list of conditions and the following disclaimer.
#     2. Redistributions in binary form must reproduce the above copyright
#        notice, this list of conditions and the following disclaimer in the
#        documentation and/or other materials provided with the distribution.
#     3. Neither the name of the copyright holder nor the names of
#        its contributors may be used to endorse or promote products
#        derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

'''Simple Histogram function for multiple neurons
'''
import numpy as np
from neurom.view import common
from itertools import chain

def histogram(neurons, feature, new_fig=True, subplot=False, normed=False, **kwargs):
    '''
    Plot a histogram of the selected feature for the population of neurons.
    Plots x-axis versus y-axis on a scatter|histogram|binned values plot.

    More information about the plot and how it works.

    Parameters
    ----------
    neurons : list
        List of Neurons. Single neurons must be encapsulated in a list.

    feature : str
    The feature of interest.

    Options
    -------
    bins : int
    Number of bins for the histogram.

    cumulative : bool
    Sets cumulative histogram on.

    subplot : bool
        Default is False, which returns a matplotlib figure object. If True,
        returns a matplotlib axis object, for use as a subplot.

    Returns
    -------
    figure_output : list
        [fig|ax, figdata, figtext]
        The first item is either a figure object (if subplot is False) or an
        axis object. The second item is an object containing the data used to
        generate the figure. The final item is text used in report generation
        as a figure legend. This text needs to be manually entered in each
        figure file.
    '''

    bins = kwargs.get('bins', 25)
    cumulative = kwargs.get('cumulative', False)

    fig, ax = common.get_figure(new_fig=new_fig, subplot=subplot)

    kwargs['xlabel'] = kwargs.get('xlabel', feature)

    kwargs['ylabel'] = kwargs.get('ylabel', feature + ' fraction')

    kwargs['title'] = kwargs.get('title', feature + ' histogram')

    feature_values = [getattr(neu, 'get_' + feature)() for neu in neurons]

    neu_labels = [neu.name for neu in neurons]

    ax.hist(feature_values, bins=bins, cumulative=cumulative, label=neu_labels, normed=normed)

    kwargs['no_legend'] = len(neu_labels) == 1

    return common.plot_style(fig=fig, ax=ax, **kwargs)

def population_feature_values(pops, feature):
    '''Extracts feature values per population
    '''
    pops_feature_values = []

    for pop in pops:

        feature_values = [getattr(neu, 'get_' + feature)() for neu in pop.neurons]

        # ugly hack to chain in case of list of lists
        if any([isinstance(p, (list, np.ndarray)) for p in feature_values]):

            feature_values = list(chain(*feature_values))

        pops_feature_values.append(feature_values)

    return pops_feature_values

def population_histogram(pops, feature, new_fig=True, normed=False, subplot=False, **kwargs):
    '''
    Plot a histogram of the selected feature for the population of neurons.
    Plots x-axis versus y-axis on a scatter|histogram|binned values plot.

    More information about the plot and how it works.

    Parameters

        populations : populations list

        feature : str
        The feature of interest.

    Options

        bins : int
        Number of bins for the histogram.

        cumulative : bool
        Sets cumulative histogram on.

        subplot : bool
            Default is False, which returns a matplotlib figure object. If True,
            returns a matplotlib axis object, for use as a subplot.

    Returns

        figure_output : list
            [fig|ax, figdata, figtext]
            The first item is either a figure object (if subplot is False) or an
            axis object. The second item is an object containing the data used to
            generate the figure. The final item is text used in report generation
            as a figure legend. This text needs to be manually entered in each
            figure file.
    '''

    bins = kwargs.get('bins', 25)
    cumulative = kwargs.get('cumulative', False)

    fig, ax = common.get_figure(new_fig=new_fig, subplot=subplot)

    kwargs['xlabel'] = kwargs.get('xlabel', feature)

    kwargs['ylabel'] = kwargs.get('ylabel', feature + ' fraction')

    kwargs['title'] = kwargs.get('title', feature + ' histogram')

    pops_feature_values = population_feature_values(pops, feature)

    pops_labels = [pop.name for pop in pops]

    ax.hist(pops_feature_values, bins=bins, cumulative=cumulative, label=pops_labels, normed=normed)

    kwargs['no_legend'] = len(pops_labels) == 1

    return common.plot_style(fig=fig, ax=ax, **kwargs)
<|endoftext|>


<commit_before>#
# Copyright 2016 The BigDL Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import sys
from bigdl.util.common import JavaValue
from bigdl.util.common import callBigDlFunc
from bigdl.util.common import *

if sys.version >= '3':
    long = int
    unicode = str

class Preprocessing(JavaValue):
    """
    Preprocessing defines data transform action during feature preprocessing. Python wrapper for
    the scala Preprocessing
    """
    def __init__(self, bigdl_type="float", *args):
        self.value = callBigDlFunc(
                bigdl_type, JavaValue.jvm_class_constructor(self), *args)

class ChainedPreprocessing(Preprocessing):
    """
    chains two Preprocessing together. The output type of the first
    Preprocessing should be the same with the input type of the second Preprocessing.
    """
    def __init__(self, transformers, bigdl_type="float"):
        for transfomer in transformers:
            assert transfomer.__class__.__bases__[0].__name__ in [
                "Preprocessing"], \
                str(transfomer) + " should be subclass of Preprocessing"
        super(ChainedPreprocessing, self).__init__(bigdl_type, transformers)

class NumToTensor(Preprocessing):
    """
    a Transformer that converts a number to a Tensor.
    """
    def __init__(self, bigdl_type="float"):
        super(NumToTensor, self).__init__(bigdl_type)

class SeqToTensor(Preprocessing):
    """
    a Transformer that converts an Array[_] or Seq[_] to a Tensor.
    :param size dimensions of target Tensor.
    """
    def __init__(self, size, bigdl_type="float"):
        super(SeqToTensor, self).__init__(bigdl_type, size)

class ArrayToTensor(Preprocessing):
    """
    a Transformer that converts an Array[_] to a Tensor.
    :param size dimensions of target Tensor.
    """
    def __init__(self, size, bigdl_type="float"):
        super(ArrayToTensor, self).__init__(bigdl_type, size)

class MLlibVectorToTensor(Preprocessing):
    """
    a Transformer that converts MLlib Vector to a Tensor.
    :param size dimensions of target Tensor.
    """
    def __init__(self, size, bigdl_type="float"):
        super(MLlibVectorToTensor, self).__init__(bigdl_type, size)

class ImageFeatureToTensor(Preprocessing):
    """
    a Transformer that convert ImageFeature to a Tensor.
    """
    def __init__(self, bigdl_type="float"):
        super(ImageFeatureToTensor, self).__init__(bigdl_type)

class RowToImageFeature(Preprocessing):
    """
    a Transformer that converts a Spark Row to a BigDL ImageFeature.
    """
    def __init__(self, bigdl_type="float"):
        super(RowToImageFeature, self).__init__(bigdl_type)

class FeatureLabelPreprocessing(Preprocessing):
    """
    construct a Transformer that convert (Feature, Label) tuple to a Sample.
    The returned Transformer is robust for the case label = null, in which the
    Sample is derived from Feature only.
    :param feature_transformer transformer for feature, transform F to Tensor[T]
    :param label_transformer transformer for label, transform L to Tensor[T]
    """
    def __init__(self, feature_transformer, label_transformer, bigdl_type="float"):
        super(FeatureLabelPreprocessing, self).__init__(bigdl_type, feature_transformer, label_transformer)

class TensorToSample(Preprocessing):
    """
     a Transformer that converts Tensor to Sample.
    """
    def __init__(self, bigdl_type="float"):
        super(TensorToSample, self).__init__(bigdl_type)

class FeatureToTupleAdapter(Preprocessing):
    def __init__(self, sample_transformer, bigdl_type="float"):
        super(FeatureToTupleAdapter, self).__init__(bigdl_type, sample_transformer)

<commit_msg>rename to scalarToTensor<commit_after>#
# Copyright 2016 The BigDL Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import sys
from bigdl.util.common import JavaValue
from bigdl.util.common import callBigDlFunc
from bigdl.util.common import *

if sys.version >= '3':
    long = int
    unicode = str

class Preprocessing(JavaValue):
    """
    Preprocessing defines data transform action during feature preprocessing. Python wrapper for
    the scala Preprocessing
    """
    def __init__(self, bigdl_type="float", *args):
        self.value = callBigDlFunc(
                bigdl_type, JavaValue.jvm_class_constructor(self), *args)

class ChainedPreprocessing(Preprocessing):
    """
    chains two Preprocessing together. The output type of the first
    Preprocessing should be the same with the input type of the second Preprocessing.
    """
    def __init__(self, transformers, bigdl_type="float"):
        for transfomer in transformers:
            assert transfomer.__class__.__bases__[0].__name__ in [
                "Preprocessing"], \
                str(transfomer) + " should be subclass of Preprocessing"
        super(ChainedPreprocessing, self).__init__(bigdl_type, transformers)

class ScalarToTensor(Preprocessing):
    """
    a Preprocessing that converts a number to a Tensor.
    """
    def __init__(self, bigdl_type="float"):
        super(ScalarToTensor, self).__init__(bigdl_type)

class SeqToTensor(Preprocessing):
    """
    a Transformer that converts an Array[_] or Seq[_] to a Tensor.
    :param size dimensions of target Tensor.
    """
    def __init__(self, size, bigdl_type="float"):
        super(SeqToTensor, self).__init__(bigdl_type, size)

class ArrayToTensor(Preprocessing):
    """
    a Transformer that converts an Array[_] to a Tensor.
    :param size dimensions of target Tensor.
    """
    def __init__(self, size, bigdl_type="float"):
        super(ArrayToTensor, self).__init__(bigdl_type, size)

class MLlibVectorToTensor(Preprocessing):
    """
    a Transformer that converts MLlib Vector to a Tensor.
    :param size dimensions of target Tensor.
    """
    def __init__(self, size, bigdl_type="float"):
        super(MLlibVectorToTensor, self).__init__(bigdl_type, size)

class ImageFeatureToTensor(Preprocessing):
    """
    a Transformer that convert ImageFeature to a Tensor.
    """
    def __init__(self, bigdl_type="float"):
        super(ImageFeatureToTensor, self).__init__(bigdl_type)

class RowToImageFeature(Preprocessing):
    """
    a Transformer that converts a Spark Row to a BigDL ImageFeature.
    """
    def __init__(self, bigdl_type="float"):
        super(RowToImageFeature, self).__init__(bigdl_type)

class FeatureLabelPreprocessing(Preprocessing):
    """
    construct a Transformer that convert (Feature, Label) tuple to a Sample.
    The returned Transformer is robust for the case label = null, in which the
    Sample is derived from Feature only.
    :param feature_transformer transformer for feature, transform F to Tensor[T]
    :param label_transformer transformer for label, transform L to Tensor[T]
    """
    def __init__(self, feature_transformer, label_transformer, bigdl_type="float"):
        super(FeatureLabelPreprocessing, self).__init__(bigdl_type, feature_transformer, label_transformer)

class TensorToSample(Preprocessing):
    """
     a Transformer that converts Tensor to Sample.
    """
    def __init__(self, bigdl_type="float"):
        super(TensorToSample, self).__init__(bigdl_type)

class FeatureToTupleAdapter(Preprocessing):
    def __init__(self, sample_transformer, bigdl_type="float"):
        super(FeatureToTupleAdapter, self).__init__(bigdl_type, sample_transformer)

<|endoftext|>