class Creator(Mediator): name = Param(six.string_types) organization = Param('sentry.models.Organization') scopes = Param(Iterable) webhook_url = Param(six.string_types) def call(self): self.proxy = self._create_proxy_user() self.api_app = self._create_api_application() self.app = self._create_sentry_app() return self.app def _create_proxy_user(self): return User.objects.create( username=self.name.lower(), is_sentry_app=True, ) def _create_api_application(self): return ApiApplication.objects.create(owner=self.proxy, ) def _create_sentry_app(self): return SentryApp.objects.create( name=self.name, application=self.api_app, owner=self.organization, proxy_user=self.proxy, scope_list=self.scopes, webhook_url=self.webhook_url, )
def test_default_referencing_instance(self): class Target(object): user = {'name': 'Pete'} target = Target() name = Param(six.string_types, default=lambda self: self.user['name']) assert name.default(target) == 'Pete'
class Updater(Mediator): sentry_app = Param('sentry.models.sentryapp.SentryApp') name = Param(six.string_types, required=False) scopes = Param(Iterable, required=False) webhook_url = Param(six.string_types, required=False) def call(self): self._update_name() self._update_scopes() self._update_webhook_url() self.sentry_app.save() return self.sentry_app @if_param('name') def _update_name(self): self.sentry_app.name = self.name @if_param('scopes') def _update_scopes(self): self._validate_only_added_scopes() self.sentry_app.scope_list = self.scopes @if_param('webhook_url') def _update_webhook_url(self): self.sentry_app.webhook_url = self.webhook_url def _validate_only_added_scopes(self): if any(self._scopes_removed): raise ValidationError('Cannot remove `scopes` already in use.') @property def _scopes_removed(self): return [s for s in self.sentry_app.scope_list if s not in self.scopes]
class Destroyer(Mediator): install = Param('sentry.models.SentryAppInstallation') user = Param('sentry.models.User') def call(self): self._destroy_authorization() self._destroy_grant() self._destroy_service_hooks() self._destroy_installation() return self.install def _destroy_authorization(self): self.install.authorization.delete() def _destroy_grant(self): self.install.api_grant.delete() def _destroy_service_hooks(self): hooks = ServiceHook.objects.filter( application_id=self.install.sentry_app.application_id, actor_id=self.install.id, ) for hook in hooks: service_hooks.Destroyer.run(service_hook=hook) def _destroy_installation(self): InstallationNotifier.run( install=self.install, user=self.user, action='deleted', ) self.install.delete()
class AlertRuleActionCreator(Mediator): install = Param("sentry.models.SentryAppInstallation") fields = Param(object, default=[]) # array of dicts def call(self): uri = self._fetch_sentry_app_uri() self._make_external_request(uri) return self.response def _fetch_sentry_app_uri(self): component = SentryAppComponent.objects.get( type="alert-rule-action", sentry_app=self.sentry_app ) settings = component.schema.get("settings", {}) return settings.get("uri") def _make_external_request(self, uri=None): if uri is None: raise APIError("Sentry App request url not found") self.response = external_requests.AlertRuleActionRequester.run( install=self.install, uri=uri, fields=self.fields, ) @memoize def sentry_app(self): return self.install.sentry_app
def test_default_referencing_instance(self): class Target: user = {"name": "Pete"} target = Target() name = Param((str, ), default=lambda self: self.user["name"]) assert name.default(target) == "Pete"
class Updater(Mediator): sentry_app = Param('sentry.models.SentryApp') name = Param(six.string_types, required=False) scopes = Param(Iterable, required=False) webhook_url = Param(six.string_types, required=False) def call(self): self._update_name() self._update_scopes() self._update_webhook_url() self.sentry_app.save() return self.sentry_app @if_param('name') def _update_name(self): self.sentry_app.name = self.name @if_param('scopes') def _update_scopes(self): if self.sentry_app.status == SentryAppStatus.PUBLISHED: raise APIError('Cannot update scopes on published App.') self.sentry_app.scope_list = self.scopes @if_param('webhook_url') def _update_webhook_url(self): self.sentry_app.webhook_url = self.webhook_url
class InstallationNotifier(Mediator): install = Param('sentry.models.SentryAppInstallation') user = Param('sentry.models.User') def call(self): self._send_webhook() def _send_webhook(self): safe_urlread( safe_urlopen(self.sentry_app.webhook_url, json=self.body, timeout=5) ) @property def body(self): data = SentryAppInstallationSerializer().serialize( self.install, attrs={'code': self.api_grant.code}, user=self.user, ) return app_platform_event( action='installation', install=self.install, data=data, actor=self.user, ) @memoize def sentry_app(self): return self.install.sentry_app @memoize def api_grant(self): return self.install.api_grant
def test_default_referencing_instance(self): class Target(object): user = {"name": "Pete"} target = Target() name = Param(six.string_types, default=lambda self: self.user["name"]) assert name.default(target) == "Pete"
class MockMediator(Mediator): user = Param(dict) name = Param((str, ), default=lambda self: self.user["name"]) age = Param(int, required=False) def call(self): with self.log(): pass
class MockMediator(Mediator): user = Param(dict) name = Param(six.string_types, default=lambda self: self.user['name']) age = Param(int, required=False) def call(self): with self.log(): pass
class Migrator(Mediator): integration = Param('sentry.models.integration.Integration') organization = Param('sentry.models.organization.Organization') def call(self): for project in self.projects: for plugin in plugins.for_project(project): if plugin.slug != self.integration.provider: continue if self.all_repos_migrated(plugin.slug): # Since repos are Org-level, if they're all migrated, we # can disable the Plugin for all Projects. There'd be no # Repos left, associated with the Plugin. self.disable_for_all_projects(plugin) def all_repos_migrated(self, provider): provider = 'visualstudio' if provider == 'vsts' else provider return all(r.integration_id is not None for r in self.repos_for_provider(provider)) def disable_for_all_projects(self, plugin): for project in self.projects: try: self.log(at='disable', project=project.slug, plugin=plugin.slug) plugin.disable(project=project) except NotImplementedError: pass def repos_for_provider(self, provider): return filter(lambda r: r.provider == provider, self.repositories) @property def repositories(self): return Repository.objects.filter( organization_id=self.organization.id, ) @memoize def projects(self): return list(self.organization.project_set.all()) @property def plugins(self): return [ plugins.configurable_for_project(project) for project in self.projects ] @property def _logging_context(self): return { 'org': self.organization.slug, 'integration_id': self.integration.id, 'integration_provider': self.integration.provider, }
class Preparer(Mediator): component = Param('sentry.models.SentryAppComponent') install = Param('sentry.models.SentryAppInstallation') project = Param('sentry.models.Project') def call(self): if self.component.type == 'issue-link': return self._prepare_issue_link() if self.component.type == 'stacktrace-link': return self._prepare_stacktrace_link() def _prepare_stacktrace_link(self): schema = self.component.schema uri = schema.get('uri') urlparts = list(urlparse(self.install.sentry_app.webhook_url)) urlparts[2] = uri query = {'installationId': self.install.uuid} if self.project: query['projectSlug'] = self.project.slug urlparts[4] = urlencode(query) schema.update({'url': urlunparse(urlparts)}) def _prepare_issue_link(self): schema = self.component.schema.copy() link = schema.get('link', {}) create = schema.get('create', {}) for field in link.get('required_fields', []): self._prepare_field(field) for field in link.get('optional_fields', []): self._prepare_field(field) for field in create.get('required_fields', []): self._prepare_field(field) for field in create.get('optional_fields', []): self._prepare_field(field) def _prepare_field(self, field): if 'options' in field: field.update({'choices': field['options']}) if 'uri' in field: if 'async' not in field: field.update(self._request(field['uri'])) def _request(self, uri): return SelectRequester.run( install=self.install, project=self.project, uri=uri, )
class Preparer(Mediator): component = Param("sentry.models.SentryAppComponent") install = Param("sentry.models.SentryAppInstallation") project = Param("sentry.models.Project") def call(self): if self.component.type == "issue-link": return self._prepare_issue_link() if self.component.type == "stacktrace-link": return self._prepare_stacktrace_link() def _prepare_stacktrace_link(self): schema = self.component.schema uri = schema.get("uri") urlparts = list( urlparse(force_str(self.install.sentry_app.webhook_url))) urlparts[2] = uri query = {"installationId": self.install.uuid} if self.project: query["projectSlug"] = self.project.slug urlparts[4] = urlencode(query) schema.update({"url": urlunparse(urlparts)}) def _prepare_issue_link(self): schema = self.component.schema.copy() link = schema.get("link", {}) create = schema.get("create", {}) for field in link.get("required_fields", []): self._prepare_field(field) for field in link.get("optional_fields", []): self._prepare_field(field) for field in create.get("required_fields", []): self._prepare_field(field) for field in create.get("optional_fields", []): self._prepare_field(field) def _prepare_field(self, field): if "options" in field: field.update({"choices": field["options"]}) if "uri" in field: if not field.get("skip_load_on_open"): field.update(self._request(field["uri"])) def _request(self, uri): return SelectRequester.run(install=self.install, project=self.project, uri=uri)
def test_setup(self): class Target(object): name = 1 name = Param(six.string_types) name.setup(Target, 'name') assert not hasattr(Target, 'name') assert hasattr(Target, '_name') assert Target._name == name
def test_setup(self): class Target: name = 1 name = Param((str, )) name.setup(Target, "name") assert not hasattr(Target, "name") assert hasattr(Target, "_name") assert Target._name == name
class Destroyer(Mediator): install = Param('sentry.models.SentryAppInstallation') user = Param('sentry.models.User') request = Param('rest_framework.request.Request', required=False) def call(self): self._destroy_authorization() self._destroy_grant() self._destroy_service_hooks() self._destroy_installation() return self.install def _destroy_authorization(self): if self.install.authorization: self.install.authorization.delete() def _destroy_grant(self): if self.install.api_grant_id: self.install.api_grant.delete() def _destroy_service_hooks(self): hooks = ServiceHook.objects.filter( application_id=self.install.sentry_app.application_id, actor_id=self.install.id, ) for hook in hooks: service_hooks.Destroyer.run(service_hook=hook) def _destroy_installation(self): InstallationNotifier.run( install=self.install, user=self.user, action='deleted', ) self.install.delete() def audit(self): if self.request: create_audit_entry( request=self.request, organization=self.install.organization, target_object=self.install.organization.id, event=AuditLogEntryEvent.SENTRY_APP_UNINSTALL, data={ 'sentry_app': self.install.sentry_app.name, }, ) def record_analytics(self): analytics.record( 'sentry_app.uninstalled', user_id=self.user.id, organization_id=self.install.organization_id, sentry_app=self.install.sentry_app.slug, )
class Creator(Mediator): name = Param(six.string_types) environment = Param(int, required=False) project = Param("sentry.models.Project") action_match = Param(six.string_types) filter_match = Param(six.string_types, required=False) actions = Param(Iterable) conditions = Param(Iterable) frequency = Param(int) request = Param("rest_framework.request.Request", required=False) def call(self): self.rule = self._create_rule() return self.rule def _create_rule(self): kwargs = self._get_kwargs() rule = Rule.objects.create(**kwargs) return rule def _get_kwargs(self): data = { "filter_match": self.filter_match, "action_match": self.action_match, "actions": self.actions, "conditions": self.conditions, "frequency": self.frequency, } _kwargs = { "label": self.name, "environment_id": self.environment or None, "project": self.project, "data": data, } return _kwargs
class Updater(Mediator): rule = Param("sentry.models.Rule") name = Param(six.string_types, required=False) environment = Param(int, required=False) project = Param("sentry.models.Project") action_match = Param(six.string_types, required=False) filter_match = Param(six.string_types, required=False) actions = Param(Iterable, required=False) conditions = Param(Iterable, required=False) frequency = Param(int, required=False) request = Param("rest_framework.request.Request", required=False) def call(self): self._update_name() self._update_environment() self._update_project() self._update_actions() self._update_action_match() self._update_filter_match() self._update_conditions() self._update_frequency() self.rule.save() return self.rule @if_param("name") def _update_name(self): self.rule.label = self.name def _update_environment(self): # environment can be None so we don't use the if_param decorator self.rule.environment_id = self.environment @if_param("project") def _update_project(self): self.rule.project = self.project @if_param("actions") def _update_actions(self): self.rule.data["actions"] = self.actions @if_param("action_match") def _update_action_match(self): self.rule.data["action_match"] = self.action_match @if_param("filter_match") def _update_filter_match(self): self.rule.data["filter_match"] = self.filter_match @if_param("conditions") def _update_conditions(self): self.rule.data["conditions"] = self.conditions @if_param("frequency") def _update_frequency(self): self.rule.data["frequency"] = self.frequency
class Creator(Mediator): organization = Param('sentry.models.Organization') slug = Param(six.string_types) user = Param('sentry.models.User') def call(self): self._create_authorization() self._create_api_grant() self._create_install() self._create_service_hooks() self._notify_service() self.install.is_new = True return self.install def _create_authorization(self): self.authorization = ApiAuthorization.objects.create( application_id=self.api_application.id, user_id=self.sentry_app.proxy_user.id, scope_list=self.sentry_app.scope_list, ) def _create_install(self): self.install = SentryAppInstallation.objects.create( organization_id=self.organization.id, sentry_app_id=self.sentry_app.id, authorization_id=self.authorization.id, api_grant_id=self.api_grant.id, ) def _create_api_grant(self): self.api_grant = ApiGrant.objects.create( user_id=self.sentry_app.proxy_user.id, application_id=self.api_application.id, ) def _create_service_hooks(self): service_hooks.Creator.run( application=self.api_application, actor=self.install, projects=[], organization=self.organization, events=self.sentry_app.events, url=self.sentry_app.webhook_url, ) def _notify_service(self): installation_webhook.delay(self.install.id, self.user.id) @memoize def api_application(self): return self.sentry_app.application @memoize def sentry_app(self): return SentryApp.objects.get(slug=self.slug)
class Creator(Mediator): sentry_app_installation = Param('sentry.models.SentryAppInstallation') expires_at = Param(datetime.date, default=None, required=False) # analytics and audit params generate_audit = Param(bool, default=False) user = Param('sentry.models.User') request = Param('rest_framework.request.Request', required=False) def call(self): self._create_api_token() self._create_sentry_app_installation_token() return self.sentry_app_installation_token def _create_api_token(self): self.api_token = ApiToken.objects.create( user=self.sentry_app.proxy_user, application_id=self.sentry_app.application.id, scope_list=self.sentry_app.scope_list, expires_at=self.expires_at, ) def _create_sentry_app_installation_token(self): self.sentry_app_installation_token = SentryAppInstallationToken.objects.create( api_token=self.api_token, sentry_app_installation=self.sentry_app_installation) def audit(self): from sentry.utils.audit import create_audit_entry if self.request and self.generate_audit: create_audit_entry( request=self.request, organization=self.organization, target_object=self.sentry_app_installation_token.id, event=AuditLogEntryEvent.INTERNAL_INTEGRATION_ADD_TOKEN, data={'sentry_app': self.sentry_app.name}, ) def record_analytics(self): from sentry import analytics analytics.record( 'sentry_app_installation_token.created', user_id=self.user.id, organization_id=self.organization.id, sentry_app_installation_id=self.sentry_app_installation.id, sentry_app=self.sentry_app.slug, ) @memoize def sentry_app(self): return self.sentry_app_installation.sentry_app @memoize def organization(self): return self.sentry_app_installation.organization
class InstallationNotifier(Mediator): install = Param('sentry.models.SentryAppInstallation') user = Param('sentry.models.User') action = Param(six.string_types) def call(self): self._verify_action() self._send_webhook() def _verify_action(self): if self.action not in ['created', 'deleted']: raise APIUnauthorized(u"Invalid action '{}'".format(self.action)) def _send_webhook(self): safe_urlread( safe_urlopen( url=self.sentry_app.webhook_url, data=self.request.body, headers=self.request.headers, timeout=5, )) @property def request(self): attrs = {} if self.install.is_new and self.api_grant: attrs['code'] = self.api_grant.code data = SentryAppInstallationSerializer().serialize( self.install, attrs=attrs, user=self.user, ) return AppPlatformEvent( resource='installation', action=self.action, install=self.install, data={'installation': data}, actor=self.user, ) @memoize def sentry_app(self): return self.install.sentry_app @memoize def api_grant(self): return self.install.api_grant_id and self.install.api_grant
class Destroyer(Mediator): api_token = Param("sentry.models.ApiToken") generate_audit = Param(bool, default=False) user = Param("sentry.models.User") request = Param("rest_framework.request.Request", required=False) def call(self): self._destroy_sentry_app_installation_token() self._destroy_api_token() return self.api_token def _destroy_api_token(self): self.api_token.delete() def _destroy_sentry_app_installation_token(self): install_token = SentryAppInstallationToken.objects.get( api_token=self.api_token) self.sentry_app_installation = install_token.sentry_app_installation install_token.delete() def audit(self): from sentry.utils.audit import create_audit_entry if self.request and self.generate_audit: create_audit_entry( request=self.request, organization=self.organization, target_object=self.api_token.id, event=AuditLogEntryEvent.INTERNAL_INTEGRATION_REMOVE_TOKEN, data={"sentry_app": self.sentry_app.name}, ) def record_analytics(self): from sentry import analytics analytics.record( "sentry_app_installation_token.deleted", user_id=self.user.id, organization_id=self.organization.id, sentry_app_installation_id=self.sentry_app_installation.id, sentry_app=self.sentry_app.slug, ) @memoize def sentry_app(self): return self.sentry_app_installation.sentry_app @memoize def organization(self): return self.sentry_app_installation.organization
class Creator(Mediator): name = Param(six.string_types) organization = Param('sentry.models.Organization') scopes = Param(Iterable) events = Param(Iterable, default=lambda self: []) webhook_url = Param(six.string_types) redirect_url = Param(six.string_types, required=False) is_alertable = Param(bool, default=False) schema = Param(dict, default=lambda self: {}) overview = Param(six.string_types, required=False) def call(self): self.proxy = self._create_proxy_user() self.api_app = self._create_api_application() self.app = self._create_sentry_app() self._create_ui_components() return self.app def _create_proxy_user(self): return User.objects.create( username=self.name.lower(), is_sentry_app=True, ) def _create_api_application(self): return ApiApplication.objects.create( owner_id=self.proxy.id, ) def _create_sentry_app(self): from sentry.mediators.service_hooks.creator import expand_events return SentryApp.objects.create( name=self.name, application_id=self.api_app.id, owner_id=self.organization.id, proxy_user_id=self.proxy.id, scope_list=self.scopes, events=expand_events(self.events), schema=self.schema or {}, webhook_url=self.webhook_url, redirect_url=self.redirect_url, is_alertable=self.is_alertable, overview=self.overview, ) def _create_ui_components(self): schema = self.schema or {} for element in schema.get('elements', []): SentryAppComponent.objects.create( type=element['type'], sentry_app_id=self.app.id, schema=element, )
class Destroyer(Mediator): sentry_app = Param('sentry.models.SentryApp') request = Param('rest_framework.request.Request', required=False) user = Param('sentry.models.User') def call(self): self._destroy_api_application() self._destroy_sentry_app_installations() self._destroy_proxy_user() self._destroy_sentry_app() return self.sentry_app def _destroy_sentry_app_installations(self): for install in self.sentry_app.installations.all(): notify = False if self.sentry_app.is_internal else True sentry_app_installations.Destroyer.run( install=install, user=self.sentry_app.proxy_user, notify=notify, ) def _destroy_api_application(self): self.sentry_app.application.delete() def _destroy_proxy_user(self): self.sentry_app.proxy_user.delete() def _destroy_sentry_app(self): self.sentry_app.delete() def audit(self): if self.request: create_audit_entry( request=self.request, organization=self.sentry_app.owner, target_object=self.sentry_app.owner.id, event=AuditLogEntryEvent.SENTRY_APP_REMOVE, data={ 'sentry_app': self.sentry_app.name, }, ) def record_analytics(self): analytics.record( 'sentry_app.deleted', user_id=self.user.id, organization_id=self.sentry_app.owner.id, sentry_app=self.sentry_app.slug, )
class Updater(Mediator): sentry_app = Param('sentry.models.SentryApp') name = Param(six.string_types, required=False) scopes = Param(Iterable, required=False) events = Param(Iterable, required=False) webhook_url = Param(six.string_types, required=False) redirect_url = Param(six.string_types, required=False) is_alertable = Param(bool, required=False) overview = Param(six.string_types, required=False) def call(self): self._update_name() self._update_scopes() self._update_events() self._update_webhook_url() self._update_redirect_url() self._update_is_alertable() self._update_overview() self.sentry_app.save() return self.sentry_app @if_param('name') def _update_name(self): self.sentry_app.name = self.name @if_param('scopes') def _update_scopes(self): if self.sentry_app.status == SentryAppStatus.PUBLISHED: raise APIError('Cannot update scopes on published App.') self.sentry_app.scope_list = self.scopes @if_param('events') def _update_events(self): for event in self.events: needed_scope = REQUIRED_EVENT_PERMISSIONS[event] if needed_scope not in self.sentry_app.scope_list: raise APIError( u'{} webhooks require the {} permission.'.format( event, needed_scope), ) from sentry.mediators.service_hooks.creator import expand_events self.sentry_app.events = expand_events(self.events) @if_param('webhook_url') def _update_webhook_url(self): self.sentry_app.webhook_url = self.webhook_url @if_param('redirect_url') def _update_redirect_url(self): self.sentry_app.redirect_url = self.redirect_url @if_param('is_alertable') def _update_is_alertable(self): self.sentry_app.is_alertable = self.is_alertable @if_param('overview') def _update_overview(self): self.sentry_app.overview = self.overview
class Destroyer(Mediator): sentry_app = Param('sentry.models.SentryApp') def call(self): self._destroy_sentry_app_installations() self._destroy_api_application() self._destroy_proxy_user() self._destroy_sentry_app() return self.sentry_app def _destroy_sentry_app_installations(self): for install in self.sentry_app.installations.all(): sentry_app_installations.Destroyer.run( install=install, user=self.sentry_app.proxy_user, ) def _destroy_api_application(self): self.sentry_app.application.delete() def _destroy_proxy_user(self): self.sentry_app.proxy_user.delete() def _destroy_sentry_app(self): self.sentry_app.delete()
class IssueLinkCreator(Mediator): install = Param('sentry.models.SentryAppInstallation') group = Param('sentry.models.Group') action = Param(six.string_types) fields = Param(object) uri = Param(six.string_types) def call(self): self._verify_action() self._make_external_request() self._create_external_issue() return self.external_issue def _verify_action(self): if self.action not in ['link', 'create']: return APIUnauthorized() def _make_external_request(self): self.response = external_requests.IssueLinkRequester.run( install=self.install, uri=self.uri, group=self.group, fields=self.fields, ) def _format_response_data(self): web_url = self.response['webUrl'] display_name = u'{}#{}'.format( self.response['project'], self.response['identifier'], ) return [web_url, display_name] def _create_external_issue(self): web_url, display_name = self._format_response_data() self.external_issue = PlatformExternalIssue.objects.create( group_id=self.group.id, service_type=self.sentry_app.slug, display_name=display_name, web_url=web_url, ) @memoize def sentry_app(self): return self.install.sentry_app
class Destroyer(Mediator): service_hook = Param("sentry.models.ServiceHook") def call(self): self._destroy_service_hook() return self.service_hook def _destroy_service_hook(self): self.service_hook.delete()
class Creator(Mediator): organization = Param('sentry.models.Organization') slug = Param(six.string_types) user = Param('sentry.models.User') def call(self): self._create_authorization() self._create_api_grant() self._create_install() self._notify_service() self.install.is_new = True return (self.install, self.api_grant) def _create_authorization(self): self.authorization = ApiAuthorization.objects.create( application=self.api_application, user=self.sentry_app.proxy_user, scope_list=self.sentry_app.scope_list, ) def _create_install(self): self.install = SentryAppInstallation.objects.create( organization=self.organization, sentry_app=self.sentry_app, authorization=self.authorization, api_grant=self.api_grant, ) def _create_api_grant(self): self.api_grant = ApiGrant.objects.create( user=self.sentry_app.proxy_user, application=self.api_application, ) def _notify_service(self): installation_webhook.delay(self.install.id, self.user.id) @memoize def api_application(self): return self.sentry_app.application @memoize def sentry_app(self): return SentryApp.objects.get(slug=self.slug)
def test_lambda_default(self): _name = 'Steve' name = Param(six.string_types, default=lambda self: _name) assert name.default(None) == 'Steve'
def test_validate_required(self): name = Param(six.string_types) with self.assertRaises(AttributeError): name.validate(None, 'name', None)
def test_validate_default_type(self): name = Param(six.string_types, default=1) with self.assertRaises(TypeError): name.validate(None, 'name', None)
def test_validate_user_defined_type(self): user = Param('sentry.models.user.User') assert user.validate(None, 'user', User())
def test_default(self): name = Param(six.string_types, default='Pete') assert name.default(None) == 'Pete'