2013-05-29 19:59:36 +04:00
|
|
|
from ordereddict import OrderedDict
|
|
|
|
|
|
|
|
from django.conf import settings
|
|
|
|
|
2013-04-19 19:09:44 +04:00
|
|
|
from tower import ugettext_lazy as _lazy
|
|
|
|
|
|
|
|
|
|
|
|
# WARNING: When adding a new app feature here also include a migration.
|
|
|
|
#
|
|
|
|
# WARNING: Order matters here. Don't re-order these or alphabetize them. If you
|
|
|
|
# add new ones put them on the end.
|
|
|
|
#
|
|
|
|
# These are used to dynamically generate the field list for the AppFeatures
|
|
|
|
# django model in mkt.webapps.models.
|
2013-06-12 04:44:56 +04:00
|
|
|
APP_FEATURES = OrderedDict([
|
|
|
|
('APPS', {
|
2013-06-26 03:37:08 +04:00
|
|
|
'name': _lazy(u'App Management API'),
|
|
|
|
'description': _lazy(u'The app requires the `navigator.mozApps` API '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'to install and manage other apps.'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('navigator.mozApps',),
|
|
|
|
}),
|
|
|
|
('PACKAGED_APPS', {
|
2013-06-26 03:37:08 +04:00
|
|
|
'name': _lazy(u'Packaged Apps Install API'),
|
|
|
|
'description': _lazy(
|
|
|
|
u'The app requires the `navigator.mozApps.installPackage` API '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'to install other packaged apps.'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('navigator.mozApps.installPackage',),
|
|
|
|
}),
|
|
|
|
('PAY', {
|
|
|
|
'name': _lazy(u'Web Payment'),
|
|
|
|
'description': _lazy(u'The app requires the `navigator.mozApps` API.'),
|
|
|
|
'apis': ('navigator.pay', 'navigator.mozPay',),
|
|
|
|
}),
|
|
|
|
('ACTIVITY', {
|
|
|
|
'name': _lazy(u'Web Activities'),
|
|
|
|
'description': _lazy(u'The app requires Web Activities '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'(the `MozActivity` API).'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('MozActivity',),
|
|
|
|
}),
|
|
|
|
('LIGHT_EVENTS', {
|
|
|
|
'name': _lazy(u'Ambient Light Sensor'),
|
|
|
|
'description': _lazy(u'The app requires an ambient light sensor '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'(the `ondevicelight` API).'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('window.ondevicelight',),
|
|
|
|
}),
|
|
|
|
('ARCHIVE', {
|
|
|
|
'name': _lazy(u'Archive'),
|
|
|
|
'description': u'',
|
|
|
|
'apis': (),
|
|
|
|
}),
|
|
|
|
('BATTERY', {
|
|
|
|
'name': _lazy(u'Battery'),
|
|
|
|
'description': _lazy(u'The app requires the `navigator.battery` API.'),
|
|
|
|
'apis': ('navigator.battery',),
|
|
|
|
}),
|
|
|
|
('BLUETOOTH', {
|
|
|
|
'name': u'Bluetooth',
|
|
|
|
'description': _lazy(u'The app requires the `navigator.mozBluetooth` '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'API.'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('navigator.bluetooth', 'navigator.mozBluetooth'),
|
|
|
|
}),
|
|
|
|
('CONTACTS', {
|
|
|
|
'name': _lazy(u'Contacts'),
|
|
|
|
'description': _lazy(u'The app requires the `navigator.mozContacts` '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'API.'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('navigator.contacts', 'navigator.mozContacts'),
|
|
|
|
}),
|
|
|
|
('DEVICE_STORAGE', {
|
|
|
|
'name': _lazy(u'Device Storage'),
|
|
|
|
'description': _lazy(u'The app requires the Device Storage API to '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'access files on the filesystem.'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('navigator.getDeviceStorage',),
|
|
|
|
}),
|
|
|
|
('INDEXEDDB', {
|
|
|
|
'name': u'IndexedDB',
|
|
|
|
'description': _lazy(u'The app requires the platform to support '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'IndexedDB.'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('navigator.indexedDB', 'navigator.mozIndexedDB'),
|
|
|
|
}),
|
|
|
|
('GEOLOCATION', {
|
|
|
|
'name': _lazy(u'Geolocation'),
|
|
|
|
'description': _lazy(u'The app requires the platform to support the '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'`navigator.geolocation` API.'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('navigator.geolocation',),
|
|
|
|
}),
|
|
|
|
('IDLE', {
|
|
|
|
'name': _lazy(u'Idle'),
|
|
|
|
'description': u'',
|
|
|
|
'apis': ('addIdleObserver', 'removeIdleObserver'),
|
|
|
|
}),
|
|
|
|
('NETWORK_INFO', {
|
|
|
|
'name': _lazy(u'Network Information'),
|
|
|
|
'description': _lazy(u'The app requires the ability to get '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'information about the network connection (the '
|
|
|
|
u'`navigator.mozConnection` API).'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('navigator.mozConnection', 'navigator.mozMobileConnection'),
|
|
|
|
}),
|
|
|
|
('NETWORK_STATS', {
|
|
|
|
'name': _lazy(u'Network Stats'),
|
|
|
|
'description': _lazy(u'The app requires the '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'`navigator.mozNetworkStats` API.'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('navigator.networkStats', 'navigator.mozNetworkStats'),
|
|
|
|
}),
|
|
|
|
('PROXIMITY', {
|
|
|
|
'name': _lazy(u'Proximity'),
|
|
|
|
'description': _lazy(u'The app requires a proximity sensor (the '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'`ondeviceproximity` API).'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('navigator.ondeviceproximity',),
|
|
|
|
}),
|
|
|
|
('PUSH', {
|
|
|
|
'name': _lazy(u'Simple Push'),
|
|
|
|
'description': _lazy(u'The app requires the `navigator.mozPush` API.'),
|
|
|
|
'apis': ('navigator.push', 'navigator.mozPush'),
|
|
|
|
}),
|
|
|
|
('ORIENTATION', {
|
|
|
|
'name': _lazy(u'Screen Orientation'),
|
|
|
|
'description': _lazy(u'The app requires the platform to support the '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'`ondeviceorientation` API.'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('ondeviceorientation',),
|
|
|
|
}),
|
|
|
|
('TIME_CLOCK', {
|
|
|
|
'name': _lazy(u'Time/Clock'),
|
|
|
|
'description': _lazy(u'The app requires the `navigator.mozTime` API.'),
|
|
|
|
'apis': ('navigator.time', 'navigator.mozTime'),
|
|
|
|
}),
|
|
|
|
('VIBRATE', {
|
|
|
|
'name': _lazy(u'Vibration'),
|
|
|
|
'description': _lazy(u'The app requires the device to support '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'vibration (the `navigator.vibrate` API).'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('navigator.vibrate',),
|
|
|
|
}),
|
|
|
|
('FM', {
|
|
|
|
'name': u'WebFM',
|
|
|
|
'description': _lazy(u'The app requires the `navigator.mozFM` or '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'`navigator.mozFMRadio` APIs.'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('navigator.mozFM', 'navigator.mozFMRadio'),
|
|
|
|
}),
|
|
|
|
('SMS', {
|
|
|
|
'name': u'WebSMS',
|
|
|
|
'description': _lazy(u'The app requires the `navigator.mozSms` API.'),
|
|
|
|
'apis': ('navigator.mozSms', 'navigator.mozSMS'),
|
|
|
|
}),
|
|
|
|
('TOUCH', {
|
|
|
|
'name': _lazy(u'Touch'),
|
|
|
|
'description': _lazy(u'The app requires the platform to support touch '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'events. This option indicates that the app '
|
|
|
|
u'will not function when used with a mouse.'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('window.ontouchstart',),
|
|
|
|
}),
|
|
|
|
('QHD', {
|
2013-07-19 22:36:22 +04:00
|
|
|
'name': _lazy(u'Smartphone-Sized Displays (qHD)'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'description': _lazy(u'The app requires the platform to have a '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'smartphone-sized display (having qHD '
|
|
|
|
u'resolution). This option indicates that the '
|
|
|
|
u'app will be unusable on larger displays '
|
2013-07-19 22:36:22 +04:00
|
|
|
u'(e.g., tablets, desktop, large or high-DPI '
|
|
|
|
u'phones).'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': (),
|
|
|
|
}),
|
|
|
|
('MP3', {
|
|
|
|
'name': u'MP3',
|
|
|
|
'description': _lazy(u'The app requires that the platform can decode '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'and play MP3 files.'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': (),
|
|
|
|
}),
|
|
|
|
('AUDIO', {
|
|
|
|
'name': _lazy(u'Audio'),
|
|
|
|
'description': _lazy(u'The app requires that the platform supports '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'the HTML5 audio API.'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('Audio',),
|
|
|
|
}),
|
|
|
|
('WEBAUDIO', {
|
|
|
|
'name': _lazy(u'Web Audio'),
|
|
|
|
'description': _lazy(u'The app requires that the platform supports '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'the Web Audio API (`window.AudioContext`).'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('AudioContext', 'mozAudioContext', 'webkitAudioContext'),
|
|
|
|
}),
|
|
|
|
('VIDEO_H264', {
|
|
|
|
'name': u'H.264',
|
|
|
|
'description': _lazy(u'The app requires that the platform can decode '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'and play H.264 video files.'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': (),
|
|
|
|
}),
|
|
|
|
('VIDEO_WEBM', {
|
|
|
|
'name': u'WebM',
|
|
|
|
'description': _lazy(u'The app requires that the platform can decode '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'and play WebM video files (VP8).'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': (),
|
|
|
|
}),
|
|
|
|
('FULLSCREEN', {
|
|
|
|
'name': _lazy(u'Full Screen'),
|
|
|
|
'description': _lazy(u'The app requires the Full Screen API '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'(`requestFullScreen` or '
|
|
|
|
u'`mozRequestFullScreen`).'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('document.documentElement.requestFullScreen',),
|
|
|
|
}),
|
|
|
|
('GAMEPAD', {
|
|
|
|
'name': _lazy(u'Gamepad'),
|
|
|
|
'description': _lazy(u'The app requires the platform to support the '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'gamepad API (`navigator.getGamepads`).'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('navigator.getGamepad', 'navigator.mozGetGamepad'),
|
|
|
|
}),
|
|
|
|
('QUOTA', {
|
|
|
|
'name': _lazy(u'Quota Management'),
|
|
|
|
'description': _lazy(u'The app requires the platform to allow '
|
2013-06-26 09:24:05 +04:00
|
|
|
u'persistent storage limit increases above the '
|
|
|
|
u'normally allowed limits for an app '
|
|
|
|
u'(`window.StorageInfo` or '
|
|
|
|
u'`window.persistentStorage`).'),
|
2013-06-12 04:44:56 +04:00
|
|
|
'apis': ('navigator.persistentStorage', 'navigator.temporaryStorage'),
|
|
|
|
}),
|
2013-08-31 01:10:11 +04:00
|
|
|
('CAMERA', {
|
|
|
|
'name': _lazy(u'Camera'),
|
|
|
|
'description': _lazy(u'The app requires the platform to allow access '
|
2013-09-04 01:55:31 +04:00
|
|
|
u'to video from the device camera via a '
|
|
|
|
u'LocalMediaStream object.'),
|
|
|
|
'apis': ('navigator.getUserMedia({video: true, picture: true})',),
|
2013-08-31 01:10:11 +04:00
|
|
|
}),
|
|
|
|
('MIC', {
|
|
|
|
'name': _lazy(u'Microphone'),
|
|
|
|
'description': _lazy(u'The app requires the platform to allow access '
|
|
|
|
u'to audio from the device microphone.'),
|
2013-09-04 01:55:31 +04:00
|
|
|
'apis': ('navigator.getUserMedia({audio: true})',),
|
2013-08-31 01:10:11 +04:00
|
|
|
}),
|
|
|
|
('SCREEN_CAPTURE', {
|
|
|
|
'name': _lazy(u'Screen Capture'),
|
|
|
|
'description': _lazy(u'The app requires the platform to allow access '
|
|
|
|
u'to the device screen for capture.'),
|
2013-09-04 01:55:31 +04:00
|
|
|
'apis': ('navigator.getUserMedia({video: {mandatory: '
|
|
|
|
'{chromeMediaSource: "screen"}}})',),
|
2013-08-31 01:10:11 +04:00
|
|
|
}),
|
|
|
|
('WEBRTC_MEDIA', {
|
2013-09-04 01:55:31 +04:00
|
|
|
'name': _lazy(u'WebRTC MediaStream'),
|
2013-08-31 01:10:11 +04:00
|
|
|
'description': _lazy(u'The app requires the platform to allow web '
|
|
|
|
u'real-time communication browser-to-browser '
|
|
|
|
u'inbound media streams.'),
|
2013-09-04 01:55:31 +04:00
|
|
|
'apis': ('MediaStream',),
|
2013-08-31 01:10:11 +04:00
|
|
|
}),
|
|
|
|
('WEBRTC_DATA', {
|
2013-09-04 01:55:31 +04:00
|
|
|
'name': _lazy(u'WebRTC DataChannel'),
|
2013-08-31 01:10:11 +04:00
|
|
|
'description': _lazy(u'The app requires the platform to allow '
|
|
|
|
u'peer-to-peer exchange of data other than audio '
|
|
|
|
u'and video.'),
|
2013-09-04 01:55:31 +04:00
|
|
|
'apis': ('DataChannel',),
|
2013-08-31 01:10:11 +04:00
|
|
|
}),
|
|
|
|
('WEBRTC_PEER', {
|
2013-09-04 01:55:31 +04:00
|
|
|
'name': _lazy(u'WebRTC PeerConnection'),
|
2013-08-31 01:10:11 +04:00
|
|
|
'description': _lazy(u'The app requires the platform to allow '
|
|
|
|
u'communication of streaming data between '
|
|
|
|
u'peers.'),
|
|
|
|
'apis': ('RTCPeerConnection',),
|
|
|
|
}),
|
|
|
|
('SPEECH_SYN', {
|
|
|
|
'name': _lazy(u'Web Speech Synthesis'),
|
|
|
|
'description': _lazy(u'The app requires the platform to allow the use '
|
|
|
|
u'of text-to-speech.'),
|
|
|
|
'apis': ('SpeechSynthesis',)
|
|
|
|
}),
|
|
|
|
('SPEECH_REC', {
|
|
|
|
'name': _lazy(u'Web Speech Recognition'),
|
|
|
|
'description': _lazy(u'The app requires the platform to allow '
|
|
|
|
u'the use of speech-to-text.'),
|
|
|
|
'apis': ('SpeechRecognition',)
|
|
|
|
}),
|
|
|
|
('POINTER_LOCK', {
|
|
|
|
'name': _lazy(u'Pointer Lock'),
|
|
|
|
'description': _lazy(u'The app requires the platform to provide '
|
|
|
|
u'additional information and control about the '
|
|
|
|
u'pointer.'),
|
|
|
|
'apis': ('document.documentElement.requestPointerLock',)
|
|
|
|
}),
|
|
|
|
('NOTIFICATION', {
|
|
|
|
'name': _lazy(u'Notifications'),
|
|
|
|
'description': _lazy(u'The app requires the platform to allow the '
|
|
|
|
u'displaying phone and desktop notifications to '
|
|
|
|
u'the user.'),
|
|
|
|
'apis': ('Notification', 'navigator.mozNotification')
|
|
|
|
}),
|
|
|
|
('ALARM', {
|
|
|
|
'name': _lazy(u'Alarms'),
|
|
|
|
'description': _lazy(u'The app requires the platform to provide '
|
|
|
|
u'access to the device alarm settings to '
|
|
|
|
u'schedule notifications and events at specific '
|
|
|
|
u'time.'),
|
|
|
|
'apis': ('navigator.mozAlarms',)
|
|
|
|
}),
|
2013-09-04 00:50:47 +04:00
|
|
|
('SYSTEMXHR', {
|
2013-08-31 01:10:11 +04:00
|
|
|
'name': _lazy(u'SystemXHR'),
|
|
|
|
'description': _lazy(u'The app requires the platform to allow the '
|
2013-09-04 01:55:31 +04:00
|
|
|
u'sending of asynchronous HTTP requests without '
|
|
|
|
u'the restrictions of the same-origin policy.'),
|
|
|
|
'apis': ('XMLHttpRequest({mozSystem: true})',)
|
2013-08-31 01:10:11 +04:00
|
|
|
}),
|
|
|
|
('TCPSOCKET', {
|
|
|
|
'name': _lazy(u'TCP Sockets'),
|
|
|
|
'description': _lazy(u'The app requires the platform to allow opening '
|
|
|
|
u'raw TCP sockets.'),
|
|
|
|
'apis': ('TCPSocket', 'navigator.mozTCPSocket',
|
|
|
|
'navigator.mozTCPServerSocket')
|
|
|
|
}),
|
2013-10-10 23:02:40 +04:00
|
|
|
('THIRDPARTY_KEYBOARD_SUPPORT', {
|
|
|
|
'name': _lazy(u'Third-Party Keyboard Support'),
|
|
|
|
'description': _lazy(u'The app requires the platform to support '
|
|
|
|
u'third-party keyboards.'),
|
|
|
|
'apis': ('navigator.mozInputMethod',),
|
|
|
|
}),
|
2013-06-12 04:44:56 +04:00
|
|
|
])
|
2013-05-31 03:25:38 +04:00
|
|
|
|
2013-05-29 19:59:36 +04:00
|
|
|
|
|
|
|
class FeatureProfile(OrderedDict):
|
|
|
|
"""
|
|
|
|
Convenience class for performing conversion operations on feature profile
|
|
|
|
representations.
|
|
|
|
"""
|
|
|
|
|
2013-06-19 01:37:12 +04:00
|
|
|
def __init__(self, **kwargs):
|
|
|
|
"""
|
|
|
|
Creates a FeatureProfile object.
|
|
|
|
|
|
|
|
Takes kwargs to the features to enable or disable. Features not
|
|
|
|
specified but that are in APP_FEATURES will be False by default.
|
|
|
|
|
|
|
|
E.g.:
|
|
|
|
|
|
|
|
>>> FeatureProfile(sms=True).to_signature()
|
|
|
|
'400.32.1'
|
|
|
|
|
|
|
|
"""
|
|
|
|
super(FeatureProfile, self).__init__()
|
|
|
|
for af in APP_FEATURES:
|
2013-06-12 04:44:56 +04:00
|
|
|
key = af.lower()
|
2013-06-19 01:37:12 +04:00
|
|
|
self[key] = kwargs.get(key, False)
|
|
|
|
|
2013-05-29 19:59:36 +04:00
|
|
|
@classmethod
|
2013-06-29 06:37:56 +04:00
|
|
|
def from_int(cls, features):
|
2013-05-29 19:59:36 +04:00
|
|
|
"""
|
2013-06-29 06:37:56 +04:00
|
|
|
Construct a FeatureProfile object from a integer bitfield.
|
2013-05-29 19:59:36 +04:00
|
|
|
|
2013-06-29 06:37:56 +04:00
|
|
|
>>> FeatureProfile.from_int(0x42)
|
2013-05-29 19:59:36 +04:00
|
|
|
FeatureProfile([('apps', False), ('packaged_apps', True), ...)
|
|
|
|
"""
|
|
|
|
instance = cls()
|
2013-06-29 06:37:56 +04:00
|
|
|
for i, k in enumerate(reversed(APP_FEATURES)):
|
|
|
|
instance[k.lower()] = bool(features & 1 << i)
|
2013-05-29 19:59:36 +04:00
|
|
|
return instance
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def from_signature(cls, signature):
|
|
|
|
"""
|
|
|
|
Construct a FeatureProfile object from a decimal signature.
|
|
|
|
|
|
|
|
>>> FeatureProfile.from_signature('40000000.32.1')
|
|
|
|
FeatureProfile([('apps', False), ('packaged_apps', True), ...)
|
|
|
|
"""
|
|
|
|
dehexed = int(signature.split('.')[0], 16)
|
2013-06-29 06:37:56 +04:00
|
|
|
return cls.from_int(dehexed)
|
2013-05-29 19:59:36 +04:00
|
|
|
|
2013-06-29 06:37:56 +04:00
|
|
|
def to_int(self):
|
2013-05-29 19:59:36 +04:00
|
|
|
"""
|
2013-06-29 06:37:56 +04:00
|
|
|
Convert a FeatureProfile object to an integer bitfield.
|
2013-05-29 19:59:36 +04:00
|
|
|
|
2013-06-29 06:37:56 +04:00
|
|
|
>>> profile.to_int()
|
|
|
|
66
|
2013-05-29 19:59:36 +04:00
|
|
|
"""
|
2013-06-29 06:37:56 +04:00
|
|
|
features = 0
|
|
|
|
for i, v in enumerate(reversed(self.values())):
|
|
|
|
features |= bool(v) << i
|
|
|
|
return features
|
2013-05-29 19:59:36 +04:00
|
|
|
|
|
|
|
def to_signature(self):
|
|
|
|
"""
|
|
|
|
Convert a FeatureProfile object to its decimal signature.
|
|
|
|
|
|
|
|
>>> profile.to_signature()
|
|
|
|
'40000000.32.1'
|
|
|
|
"""
|
2013-06-29 06:37:56 +04:00
|
|
|
return '%x.%s.%s' % (self.to_int(), len(self),
|
2013-05-29 19:59:36 +04:00
|
|
|
settings.APP_FEATURES_VERSION)
|
|
|
|
|
2013-06-12 00:46:29 +04:00
|
|
|
def to_list(self):
|
|
|
|
"""
|
|
|
|
Returns a list representing the true values of this profile.
|
|
|
|
"""
|
|
|
|
return [k for k, v in self.iteritems() if v]
|
|
|
|
|
2013-06-08 04:11:23 +04:00
|
|
|
def to_kwargs(self, prefix=''):
|
2013-05-29 19:59:36 +04:00
|
|
|
"""
|
2013-06-08 04:11:23 +04:00
|
|
|
Returns a dict representing the false values of this profile.
|
2013-05-29 19:59:36 +04:00
|
|
|
|
|
|
|
Parameters:
|
|
|
|
- `prefix` - a string prepended to the key name. Helpful if being used
|
|
|
|
to traverse relations
|
2013-06-08 04:11:23 +04:00
|
|
|
|
|
|
|
This only includes keys for which the profile is False, which is useful
|
|
|
|
for querying apps where we want to filter by apps which do not require
|
|
|
|
a feature.
|
2013-05-29 19:59:36 +04:00
|
|
|
|
|
|
|
>>> profile = FeatureProject.from_signature(request.get('pro'))
|
|
|
|
>>> Webapp.objects.filter(**profile.to_kwargs())
|
2013-06-08 04:11:23 +04:00
|
|
|
|
2013-05-29 19:59:36 +04:00
|
|
|
"""
|
2013-06-08 04:11:23 +04:00
|
|
|
return dict((prefix + k, False) for k, v in self.iteritems() if not v)
|