From: Charles Connell Date: Wed, 14 May 2014 18:26:21 +0000 (-0400) Subject: Migrate secrets to environment variables X-Git-Tag: release-20150131~72 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=aa3b27296dff8b7707645e0bbbfcc8c708222841;p=oweals%2Fkarmaworld.git Migrate secrets to environment variables --- diff --git a/.foreman b/.foreman new file mode 100644 index 0000000..267e5da --- /dev/null +++ b/.foreman @@ -0,0 +1,2 @@ +port: 8000 +procfile: Procfile-development diff --git a/Procfile-development b/Procfile-development new file mode 100644 index 0000000..13deb3a --- /dev/null +++ b/Procfile-development @@ -0,0 +1 @@ +web: python manage.py runserver "0.0.0.0:$PORT" --settings "$DJANGO_SETTINGS_MODULE" diff --git a/karmaworld/apps/notes/gdrive.py b/karmaworld/apps/notes/gdrive.py index 7bb183f..3c55c87 100644 --- a/karmaworld/apps/notes/gdrive.py +++ b/karmaworld/apps/notes/gdrive.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding:utf8 -*- # Copyright (C) 2012 FinalsClub Foundation +import base64 import datetime import logging @@ -26,13 +27,14 @@ from apiclient.discovery import build from apiclient.http import MediaInMemoryUpload from oauth2client.client import SignedJwtAssertionCredentials -import karmaworld.secret.drive as drive - logger = logging.getLogger(__name__) PDF_MIMETYPE = 'application/pdf' PPT_MIMETYPES = ['application/vnd.ms-powerpoint', 'application/vnd.openxmlformats-officedocument.presentationml.presentation'] +GOOGLE_CLIENT_SECRETS = os.environ['GOOGLE_CLIENT_SECRETS'] +GOOGLE_SERVICE_KEY_BASE64 = os.environ['GOOGLE_SERVICE_KEY_BASE64'] +GOOGLE_USER = os.environ['GOOGLE_USER'] def build_api_service(): """ @@ -47,16 +49,13 @@ def build_api_service(): """ # Extract the service address from the client secret - with open(drive.CLIENT_SECRET, 'r') as fp: - service_user = json.load(fp)['web']['client_email'] + service_user = json.loads(GOOGLE_CLIENT_SECRETS)['web']['client_email'] # Pull in the service's p12 private key. - with open(drive.SERVICE_KEY, 'rb') as p12: - # Use the private key to auth as the service user for access to the - # Google Drive of the GOOGLE_USER - credentials = SignedJwtAssertionCredentials(service_user, p12.read(), + p12 = base64.decodestring(GOOGLE_SERVICE_KEY_BASE64) + credentials = SignedJwtAssertionCredentials(service_user, p12, scope='https://www.googleapis.com/auth/drive', - sub=drive.GOOGLE_USER) + sub=GOOGLE_USER) return build('drive', 'v2', http=credentials.authorize(httplib2.Http())) diff --git a/karmaworld/apps/notes/management/commands/import_ocw_json.py b/karmaworld/apps/notes/management/commands/import_ocw_json.py index 4e43e34..33a906c 100644 --- a/karmaworld/apps/notes/management/commands/import_ocw_json.py +++ b/karmaworld/apps/notes/management/commands/import_ocw_json.py @@ -6,18 +6,17 @@ import json import os.path import requests -from apps.notes.models import Note -from apps.notes.gdrive import convert_raw_document -from apps.courses.models import Course -from apps.courses.models import School -from apps.courses.models import Professor -from apps.courses.models import Department -from apps.courses.models import ProfessorTaught -from apps.courses.models import ProfessorAffiliation -from apps.licenses.models import License -from apps.document_upload.models import RawDocument +from karmaworld.apps.notes.models import Note +from karmaworld.apps.notes.gdrive import convert_raw_document +from karmaworld.apps.courses.models import Course +from karmaworld.apps.courses.models import School +from karmaworld.apps.courses.models import Professor +from karmaworld.apps.courses.models import Department +from karmaworld.apps.licenses.models import License +from karmaworld.apps.document_upload.models import RawDocument from django.core.management.base import BaseCommand -from karmaworld.secret.filepicker import FILEPICKER_API_KEY + +FILEPICKER_API_KEY = os.environ['FILEPICKER_API_KEY'] class Command(BaseCommand): args = 'directory containing json files from mit-ocw-scraper' diff --git a/karmaworld/apps/notes/management/commands/populate_filepicker.py b/karmaworld/apps/notes/management/commands/populate_filepicker.py index 85ec805..15cd493 100644 --- a/karmaworld/apps/notes/management/commands/populate_filepicker.py +++ b/karmaworld/apps/notes/management/commands/populate_filepicker.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding:utf8 -*- # Copyright (C) 2014 FinalsClub Foundation +import os import time import json @@ -10,7 +11,8 @@ from django.utils.text import slugify from karmaworld.apps.notes.models import Note from karmaworld.utils.filepicker import sign_fp_policy, encode_fp_policy import requests -from karmaworld.secret.filepicker import FILEPICKER_API_KEY + +FILEPICKER_API_KEY = os.environ['FILEPICKER_API_KEY'] class Command(BaseCommand): diff --git a/karmaworld/apps/notes/models.py b/karmaworld/apps/notes/models.py index 9aecbcc..8710af7 100644 --- a/karmaworld/apps/notes/models.py +++ b/karmaworld/apps/notes/models.py @@ -20,7 +20,6 @@ from django.db.models import SET_NULL from django.db.models.signals import post_save, post_delete, pre_save from django.dispatch import receiver from karmaworld.apps.users.models import NoteKarmaEvent, GenericKarmaEvent -from karmaworld.secret.filepicker import FILEPICKER_API_KEY from karmaworld.utils.filepicker import encode_fp_policy, sign_fp_policy import os import time @@ -40,6 +39,8 @@ from karmaworld.apps.licenses.models import License from karmaworld.apps.notes.search import SearchIndex from karmaworld.settings.manual_unique_together import auto_add_check_unique_together +FILEPICKER_API_KEY = os.environ['FILEPICKER_API_KEY'] + ANONYMOUS_UPLOAD_URLS = 'anonymous_upload_urls' KEYWORD_MTURK_THRESHOLD = 3 diff --git a/karmaworld/apps/notes/search.py b/karmaworld/apps/notes/search.py index b18ba21..fd944af 100644 --- a/karmaworld/apps/notes/search.py +++ b/karmaworld/apps/notes/search.py @@ -3,13 +3,13 @@ # Copyright (C) 2013 FinalsClub Foundation import calendar +import os import time import uuid from django.core.exceptions import ImproperlyConfigured import indextank.client as itc from django.conf import settings -import karmaworld.secret.indexden as secret import logging @@ -20,6 +20,8 @@ MOCK_MODE = settings.TESTING logging.basicConfig() logger = logging.getLogger(__name__) +INDEXDEN_INDEX = os.environ['INDEXDEN_INDEX'] +INDEXDEN_PRIVATE_URL = os.environ['INDEXDEN_PRIVATE_URL'] class SearchResult(object): """The result of making a query into IndexDen. @@ -57,7 +59,7 @@ class SearchIndex(object): __metaclass__ = Singleton def __init__(self): - self.index_name = secret.INDEX + self.index_name = INDEXDEN_INDEX # If we're in production mode, # or if we're in testing mode with indexing @@ -66,7 +68,7 @@ class SearchIndex(object): if MOCK_MODE: return - self.api_client = itc.ApiClient(secret.PRIVATE_URL) + self.api_client = itc.ApiClient(INDEXDEN_PRIVATE_URL) if not self.api_client.get_index(self.index_name).exists(): time.sleep(5) self.api_client.create_index(self.index_name, {'public_search': False}) diff --git a/karmaworld/apps/notes/tasks.py b/karmaworld/apps/notes/tasks.py index 946ebaa..d04eef5 100644 --- a/karmaworld/apps/notes/tasks.py +++ b/karmaworld/apps/notes/tasks.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding:utf8 -*- # Copyright (C) 2013 FinalsClub Foundation +import os import traceback from celery import task @@ -16,16 +17,19 @@ def tweet_note(): """Tweet about a new note.""" try: - import karmaworld.secret.twitter as secrets - except ImportError: + TWITTER_CONSUMER_KEY = os.environ['TWITTER_CONSUMER_KEY'] + TWITTER_CONSUMER_SECRET = os.environ['TWITTER_CONSUMER_SECRET'] + TWITTER_ACCESS_TOKEN_KEY = os.environ['TWITTER_ACCESS_TOKEN_KEY'] + TWITTER_ACCESS_TOKEN_SECRET = os.environ['TWITTER_ACCESS_TOKEN_SECRET'] + except: logger.warn("No twitter secrets found, not running tweet_note") return try: - api = twitter.Api(consumer_key=secrets.CONSUMER_KEY, - consumer_secret=secrets.CONSUMER_SECRET, - access_token_key=secrets.ACCESS_TOKEN_KEY, - access_token_secret=secrets.ACCESS_TOKEN_SECRET) + api = twitter.Api(consumer_key=TWITTER_CONSUMER_KEY, + consumer_secret=TWITTER_CONSUMER_SECRET, + access_token_key=TWITTER_ACCESS_TOKEN_KEY, + access_token_secret=TWITTER_ACCESS_TOKEN_SECRET) newest_notes = Note.objects.all().order_by('-uploaded_at')[:100] for n in newest_notes: diff --git a/karmaworld/apps/quizzes/tasks.py b/karmaworld/apps/quizzes/tasks.py index 806a4b6..2fea3de 100644 --- a/karmaworld/apps/quizzes/tasks.py +++ b/karmaworld/apps/quizzes/tasks.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding:utf8 -*- # Copyright (C) 2013 FinalsClub Foundation +import os from boto.mturk.qualification import PercentAssignmentsApprovedRequirement, Qualifications from boto.mturk.question import Overview, FormattedContent, QuestionContent, Question, FreeTextAnswer, QuestionForm, \ AnswerSpecification @@ -11,6 +12,7 @@ from django.contrib.sites.models import Site from django.core.exceptions import ObjectDoesNotExist from karmaworld.apps.notes.models import Note from karmaworld.apps.quizzes.models import Keyword +from django.conf import settings logger = get_task_logger(__name__) @@ -67,12 +69,12 @@ def submit_extract_keywords_hit(note): choose keywords and definitions from the given note.""" try: - from karmaworld.secret.mturk import AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, MTURK_HOST - except ImportError: + MTURK_HOST = os.environ['MTURK_HOST'] + except: logger.warn('Could not find Mechanical Turk secrets, not running submit_extract_keywords_hit') return - connection = MTurkConnection(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, + connection = MTurkConnection(settings.AWS_ACCESS_KEY_ID, settings.AWS_SECRET_ACCESS_KEY, host=MTURK_HOST) overview = Overview() diff --git a/karmaworld/secret/__init__.py b/karmaworld/secret/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/karmaworld/secret/client_secrets.json.example b/karmaworld/secret/client_secrets.json.example deleted file mode 100644 index ac5effd..0000000 --- a/karmaworld/secret/client_secrets.json.example +++ /dev/null @@ -1,10 +0,0 @@ -{ - "web": { - "auth_uri": "https://accounts.google.com/o/oauth2/auth", - "token_uri": "https://accounts.google.com/o/oauth2/token", - "client_email": "PROJECT@developer.gserviceaccount.com", - "client_x509_cert_url":"https://www.googleapis.com/robot/v1/metadata/x509/PROJECT@developer.gserviceaccount.com", - "client_id":"PROJECT.apps.googleusercontent.com", - "auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs" - } -} diff --git a/karmaworld/secret/db_settings.py.example b/karmaworld/secret/db_settings.py.example deleted file mode 100644 index c70f70b..0000000 --- a/karmaworld/secret/db_settings.py.example +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env python -# -*- coding:utf8 -*- -# Copyright (C) 2012 FinalsClub Foundation -""" -DO NOT modify this file directly, instead copy it to db_settings.py and modify -that file. -DO NOT check db_settings.py into source control. -""" -PROD_DB_NAME = 'DB_NAME' -PROD_DB_USERNAME = 'DB_USER_NAME' -PROD_DB_PASSWORD = 'PASSWD' diff --git a/karmaworld/secret/drive.py.example b/karmaworld/secret/drive.py.example deleted file mode 100644 index 43c87ec..0000000 --- a/karmaworld/secret/drive.py.example +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python -# -*- coding:utf8 -*- -# Copyright (C) 2012 FinalsClub Foundation -""" -DO NOT modify this file directly, instead copy it to drive.py and modify -that file. -DO NOT check drive.py into source control. -""" - -import os - -from django.conf import settings - - -CLIENT_SECRET = os.path.join(settings.DJANGO_ROOT, \ - 'path/to/client_secrets.json') - -SERVICE_KEY = os.path.join(settings.DJANGO_ROOT, 'path/to/some.p12') - -GOOGLE_USER = 'GOOGLE_APPS_EMAIL_ADDRESS' diff --git a/karmaworld/secret/email.py.example b/karmaworld/secret/email.py.example deleted file mode 100644 index 1aba88a..0000000 --- a/karmaworld/secret/email.py.example +++ /dev/null @@ -1,5 +0,0 @@ - -STMP_HOST = '' -SMTP_USERNAME = '' -SMTP_PASSWORD = '' - diff --git a/karmaworld/secret/filepicker.py.example b/karmaworld/secret/filepicker.py.example deleted file mode 100644 index 4369a28..0000000 --- a/karmaworld/secret/filepicker.py.example +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python -# -*- coding:utf8 -*- -# Copyright (C) 2012 FinalsClub Foundation -""" -DO NOT modify this file directly, instead copy it to filepicker.py and modify -that file. -DO NOT check filepicker.py into source control. -""" -FILEPICKER_API_KEY = 0 -SECRET = 0 diff --git a/karmaworld/secret/indexden.py.example b/karmaworld/secret/indexden.py.example deleted file mode 100644 index 8fbb74f..0000000 --- a/karmaworld/secret/indexden.py.example +++ /dev/null @@ -1,3 +0,0 @@ - -PRIVATE_URL = '' -INDEX = '' diff --git a/karmaworld/secret/mturk.py.example b/karmaworld/secret/mturk.py.example deleted file mode 100644 index 1be49e8..0000000 --- a/karmaworld/secret/mturk.py.example +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python -# -*- coding:utf8 -*- -# Copyright (C) 2014 FinalsClub Foundation - -AWS_ACCESS_KEY_ID = '' -AWS_SECRET_ACCESS_KEY = '' -MTURK_HOST = 'mechanicalturk.sandbox.amazonaws.com' diff --git a/karmaworld/secret/static_s3.py.example b/karmaworld/secret/static_s3.py.example deleted file mode 100644 index 546a2af..0000000 --- a/karmaworld/secret/static_s3.py.example +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env python -# -*- coding:utf8 -*- -# Copyright (C) 2012 FinalsClub Foundation -""" Dummy S3 bucket conf. file (for pushing static files """ - -DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage' -AWS_ACCESS_KEY_ID = 'access_id' -AWS_SECRET_ACCESS_KEY = 'access_key' -AWS_STORAGE_BUCKET_NAME = 'bucket' -S3_URL = '//%s.s3.amazonaws.com/' % AWS_STORAGE_BUCKET_NAME diff --git a/karmaworld/secret/twitter.py.example b/karmaworld/secret/twitter.py.example deleted file mode 100644 index bf7347f..0000000 --- a/karmaworld/secret/twitter.py.example +++ /dev/null @@ -1,8 +0,0 @@ - - -CONSUMER_KEY = '' -CONSUMER_SECRET = '' -ACCESS_TOKEN_KEY = '' -ACCESS_TOKEN_SECRET = '' - - diff --git a/karmaworld/settings/common.py b/karmaworld/settings/common.py index f387ca4..0588571 100644 --- a/karmaworld/settings/common.py +++ b/karmaworld/settings/common.py @@ -3,18 +3,16 @@ # Copyright (C) 2012 FinalsClub Foundation """ Common settings and globals. """ from datetime import timedelta +from os.path import dirname, abspath, basename, normpath, join import sys -from os.path import abspath, basename, dirname, join, normpath +import os from sys import path from djcelery import setup_loader import dj_database_url -from karmaworld.secret.filepicker import FILEPICKER_API_KEY as fp_api -FILEPICKER_API_KEY = fp_api +FILEPICKER_API_KEY = os.environ['FILEPICKER_API_KEY'] FILEPICKER_INPUT_TYPE = 'filepicker' -from karmaworld.secret.static_s3 import * - SERIALIZATION_MODULES = {'json-pretty': 'karmaworld.apps.serializers.json_pretty'} @@ -22,12 +20,7 @@ SERIALIZATION_MODULES = {'json-pretty': 'karmaworld.apps.serializers.json_pretty # See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-ALLOWED_HOSTS # The hosts that this server runs from. ALLOWED_HOSTS = [ - '127.0.0.1', # for dev systems / VMs, but should be safe enough - 'localhost', # for dev systems / VMs, but should be safe enough - 'beta.karmanotes.org', - 'www.karmanotes.org', - 'karmanotes.org', - 'quiz.karmanotes.org', + '*' ] ########## END SECURITY CONFIGURATION @@ -115,6 +108,14 @@ STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'compressor.finders.CompressorFinder', ) + +S3_URL = '//%s.s3.amazonaws.com/' % os.environ.get('AWS_STORAGE_BUCKET_NAME') +DEFAULT_FILE_STORAGE = os.environ['DEFAULT_FILE_STORAGE'] + +AWS_ACCESS_KEY_ID = os.environ.get('AWS_ACCESS_KEY_ID') +AWS_SECRET_ACCESS_KEY = os.environ.get('AWS_SECRET_ACCESS_KEY') +AWS_STORAGE_BUCKET_NAME = os.environ.get('AWS_STORAGE_BUCKET_NAME') + ########## END STATIC FILE CONFIGURATION diff --git a/karmaworld/settings/prod.py b/karmaworld/settings/prod.py index 04a5bc3..0aaf1f4 100644 --- a/karmaworld/settings/prod.py +++ b/karmaworld/settings/prod.py @@ -10,9 +10,9 @@ from common import * try: # Include email is settings are there - from karmaworld.secret.email import SMTP_HOST - from karmaworld.secret.email import SMTP_USERNAME - from karmaworld.secret.email import SMTP_PASSWORD + SMTP_HOST = os.environ['SMTP_HOST'] + SMTP_USERNAME = os.environ['SMTP_USERNAME'] + SMTP_PASSWORD = os.environ['SMTP_PASSWORD'] EMAIL = True except: EMAIL = False @@ -128,7 +128,7 @@ AWS_HEADERS = { # See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url # S3_URL comes from karmaworld.secret.static_s3 -STATIC_URL = CLOUDFRONT_URL + AWS_LOCATION + '/' +STATIC_URL = os.environ.get('CLOUDFRONT_URL') + AWS_LOCATION + '/' ########## END STORAGE CONFIGURATION ########## SSL FORWARDING CONFIGURATION @@ -140,10 +140,10 @@ SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') COMPRESS_OFFLINE = True # See: http://django_compressor.readthedocs.org/en/latest/settings/#django.conf.settings.COMPRESS_STORAGE -COMPRESS_STORAGE = DEFAULT_FILE_STORAGE +COMPRESS_STORAGE = os.environ.get('DEFAULT_FILE_STORAGE') # Make sure that django-compressor serves from CloudFront -AWS_S3_CUSTOM_DOMAIN = CLOUDFRONT_DOMAIN +AWS_S3_CUSTOM_DOMAIN = os.environ.get('CLOUDFRONT_DOMAIN') # See: http://django_compressor.readthedocs.org/en/latest/settings/#django.conf.settings.COMPRESS_CSS_FILTERS COMPRESS_CSS_FILTERS += [ diff --git a/karmaworld/utils/filepicker.py b/karmaworld/utils/filepicker.py index f816c76..3bf0040 100644 --- a/karmaworld/utils/filepicker.py +++ b/karmaworld/utils/filepicker.py @@ -3,7 +3,9 @@ import json import base64 from hashlib import sha256 -from karmaworld.secret.filepicker import SECRET +import os + +FILEPCIKER_SECRET = os.environ['FILEPCIKER_SECRET'] def encode_fp_policy(policy): """ Return URL-safe Base64 encoded JSON Filepicker policy. """ @@ -23,6 +25,6 @@ def sign_fp_policy(policy): """ Return a signature appropriate for the given encoded policy. """ # https://developers.inkfilepicker.com/docs/security/#signPolicy # hash it up, bra! - engine = hmac.new(SECRET, digestmod=sha256) + engine = hmac.new(FILEPCIKER_SECRET, digestmod=sha256) engine.update(policy) return engine.hexdigest() diff --git a/manage.py b/manage.py index 891e68d..a2e9889 100755 --- a/manage.py +++ b/manage.py @@ -7,7 +7,7 @@ if __name__ == "__main__": PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__)) sys.path.append(os.path.join(PROJECT_ROOT, 'karmaworld/apps')) - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "karmaworld.settings.prod") + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "karmaworld.settings.dev") from django.core.management import execute_from_command_line diff --git a/reqs/common.txt b/reqs/common.txt deleted file mode 100644 index 27438b7..0000000 --- a/reqs/common.txt +++ /dev/null @@ -1,31 +0,0 @@ -Django>=1.5.0,<1.6.0 -django-celery==3.0.21 -django-compressor==1.2 -Fabric==1.5.3 -South==0.8.4 -supervisor==3.0b1 -oauth2client==1.0 -urllib3==1.5 -google-api-python-client==1.0 -django-grappelli==2.4.8 -django-taggit -git+https://github.com/btbonval/django-filepicker.git -filemagic==1.6 -requests -beautifulsoup4 -pyopenssl -python-twitter -gdshortener -git+https://github.com/flaptor/indextank-py.git -git+https://github.com/jhilker/html2text.git -django-allauth -boto -django-storages==1.1.4 -django-reversion -django-ajax-selects -git+https://github.com/btbonval/django-ajax-selects-cascade.git -psycopg2 -pyth -querystring_parser -gunicorn -dj-database-url diff --git a/reqs/dev.txt b/reqs/dev.txt deleted file mode 100644 index c3409b3..0000000 --- a/reqs/dev.txt +++ /dev/null @@ -1,12 +0,0 @@ --r common.txt -django-kombu==0.9.4 -django-debug-toolbar -django-debug-toolbar-template-timings -ipython==0.13.1 -ipdb==0.7 -django-extensions==1.0.3 # some extra debugging tools for manage.py -# Testing requirements -django-nose==1.1 -coverage==3.6 -selenium==2.38.4 -mock diff --git a/reqs/prod.txt b/reqs/prod.txt deleted file mode 100644 index bd4928c..0000000 --- a/reqs/prod.txt +++ /dev/null @@ -1,5 +0,0 @@ --r common.txt -cssmin==0.1.4 -pylibmc==1.2.3 -jsmin==2.0.2 -amqplib==1.0.2 diff --git a/reqs/vmdev.txt b/reqs/vmdev.txt deleted file mode 100644 index 03bc7bd..0000000 --- a/reqs/vmdev.txt +++ /dev/null @@ -1,11 +0,0 @@ --r prod.txt -django-debug-toolbar -django-debug-toolbar-template-timings -ipython==0.13.1 -ipdb==0.7 -django-extensions==1.0.3 # some extra debugging tools for manage.py -# Testing requirements -django-nose==1.1 -coverage==3.6 -selenium==2.38.4 -mock diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..d13cce4 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,11 @@ +django-kombu==0.9.4 +django-debug-toolbar +django-debug-toolbar-template-timings +ipython==0.13.1 +ipdb==0.7 +django-extensions==1.0.3 # some extra debugging tools for manage.py +# Testing requirements +django-nose==1.1 +coverage==3.6 +selenium==2.38.4 +mock diff --git a/requirements.txt b/requirements.txt index 2f3c8b2..8a3e037 100644 --- a/requirements.txt +++ b/requirements.txt @@ -29,14 +29,6 @@ pyth querystring_parser gunicorn dj-database-url -django-kombu==0.9.4 -django-debug-toolbar -ipdb==0.7 -django-extensions==1.0.3 # some extra debugging tools for manage.py -# Testing requirements -django-nose==1.1 -coverage==3.6 -selenium==2.38.4 mock cssmin==0.1.4 amqplib==1.0.2