diff --git a/lms/djangoapps/track/__init__.py b/cms/__init__.py similarity index 100% rename from lms/djangoapps/track/__init__.py rename to cms/__init__.py diff --git a/lms/lib/cache_toolbox/templatetags/__init__.py b/cms/envs/__init__.py similarity index 100% rename from lms/lib/cache_toolbox/templatetags/__init__.py rename to cms/envs/__init__.py diff --git a/cms/envs/common.py b/cms/envs/common.py new file mode 100644 index 0000000000000000000000000000000000000000..9b349a06d0d3b2c03bc49785e132b5526fc302ec --- /dev/null +++ b/cms/envs/common.py @@ -0,0 +1,151 @@ +""" +This is the common settings file, intended to set sane defaults. If you have a +piece of configuration that's dependent on a set of feature flags being set, +then create a function that returns the calculated value based on the value of +MITX_FEATURES[...]. Modules that extend this one can change the feature +configuration in an environment specific config file and re-calculate those +values. + +We should make a method that calls all these config methods so that you just +make one call at the end of your site-specific dev file to reset all the +dependent variables (like INSTALLED_APPS) for you. + +Longer TODO: +1. Right now our treatment of static content in general and in particular + course-specific static content is haphazard. +2. We should have a more disciplined approach to feature flagging, even if it + just means that we stick them in a dict called MITX_FEATURES. +3. We need to handle configuration for multiple courses. This could be as + multiple sites, but we do need a way to map their data assets. +""" + +import sys +import tempfile +from path import path + +############################# SET PATH INFORMATION ############################# +PROJECT_ROOT = path(__file__).abspath().dirname().dirname() # /mitx/cms +COMMON_ROOT = PROJECT_ROOT.dirname() / "common" +ENV_ROOT = PROJECT_ROOT.dirname().dirname() # virtualenv dir /mitx is in +ASKBOT_ROOT = ENV_ROOT / "askbot-devel" +COURSES_ROOT = ENV_ROOT / "data" + +# FIXME: To support multiple courses, we should walk the courses dir at startup +DATA_DIR = COURSES_ROOT + +sys.path.append(ENV_ROOT) +sys.path.append(ASKBOT_ROOT) +sys.path.append(ASKBOT_ROOT / "askbot" / "deps") +sys.path.append(PROJECT_ROOT / 'djangoapps') +sys.path.append(PROJECT_ROOT / 'lib') +sys.path.append(COMMON_ROOT / 'djangoapps') +sys.path.append(COMMON_ROOT / 'lib') + + +############################# WEB CONFIGURATION ############################# +# This is where we stick our compiled template files. +MAKO_MODULE_DIR = tempfile.mkdtemp('mako') +MAKO_TEMPLATES = {} +MAKO_TEMPLATES['main'] = [PROJECT_ROOT / 'templates'] + +MITX_ROOT_URL = '' + +TEMPLATE_CONTEXT_PROCESSORS = ( + 'django.core.context_processors.request', + 'django.core.context_processors.static', + 'django.contrib.messages.context_processors.messages', + 'django.core.context_processors.auth', # this is required for admin + 'django.core.context_processors.csrf', # necessary for csrf protection +) + +################################# Middleware ################################### +# List of finder classes that know how to find static files in +# various locations. +STATICFILES_FINDERS = ( + 'django.contrib.staticfiles.finders.FileSystemFinder', + 'django.contrib.staticfiles.finders.AppDirectoriesFinder', +) + +# List of callables that know how to import templates from various sources. +TEMPLATE_LOADERS = ( + 'django.template.loaders.filesystem.Loader', + 'django.template.loaders.app_directories.Loader', +) + +MIDDLEWARE_CLASSES = ( + 'django.middleware.cache.UpdateCacheMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + + # Instead of AuthenticationMiddleware, we use a cached backed version + 'cache_toolbox.middleware.CacheBackedAuthenticationMiddleware', + + 'django.contrib.messages.middleware.MessageMiddleware', + 'track.middleware.TrackMiddleware', + 'mitxmako.middleware.MakoMiddleware', + + 'django.middleware.transaction.TransactionMiddleware', +) + +############################ SIGNAL HANDLERS ################################ +import monitoring.exceptions # noqa + +############################ DJANGO_BUILTINS ################################ +# Change DEBUG/TEMPLATE_DEBUG in your environment settings files, not here +DEBUG = False +TEMPLATE_DEBUG = False + +# Site info +SITE_ID = 1 +SITE_NAME = "localhost:8000" +HTTPS = 'on' +ROOT_URLCONF = 'mitx.cms.urls' +IGNORABLE_404_ENDS = ('favicon.ico') + +# Email +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' +DEFAULT_FROM_EMAIL = 'registration@mitx.mit.edu' +DEFAULT_FEEDBACK_EMAIL = 'feedback@mitx.mit.edu' +ADMINS = ( + ('MITx Admins', 'admin@mitx.mit.edu'), +) +MANAGERS = ADMINS + +# Static content +STATIC_URL = '/static/' +ADMIN_MEDIA_PREFIX = '/static/admin/' +STATIC_ROOT = ENV_ROOT / "staticfiles" + +# FIXME: We should iterate through the courses we have, adding the static +# contents for each of them. (Right now we just use symlinks.) +STATICFILES_DIRS = [ + PROJECT_ROOT / "static", + +# This is how you would use the textbook images locally +# ("book", ENV_ROOT / "book_images") +] + +# Locale/Internationalization +TIME_ZONE = 'America/New_York' # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name +LANGUAGE_CODE = 'en' # http://www.i18nguy.com/unicode/language-identifiers.html +USE_I18N = True +USE_L10N = True + +# Messages +MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage' + +############################ APPS ##################################### + +INSTALLED_APPS = ( + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.messages', + 'django.contrib.staticfiles', + # Uncomment the next line to enable the admin: + # 'django.contrib.admin', + # Uncomment the next line to enable admin documentation: + # 'django.contrib.admindocs', +) diff --git a/cms/envs/dev.py b/cms/envs/dev.py new file mode 100644 index 0000000000000000000000000000000000000000..72a5e512c4dd34c0374bec4a00b35b752ae36c19 --- /dev/null +++ b/cms/envs/dev.py @@ -0,0 +1,37 @@ +""" +This config file runs the simplest dev environment""" + +from .common import * + +DEBUG = True +TEMPLATE_DEBUG = DEBUG + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': ENV_ROOT / "db" / "mitx.db", + } +} + +CACHES = { + # This is the cache used for most things. Askbot will not work without a + # functioning cache -- it relies on caching to load its settings in places. + # In staging/prod envs, the sessions also live here. + 'default': { + 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', + 'LOCATION': 'mitx_loc_mem_cache', + 'KEY_FUNCTION': 'util.memcache.safe_key', + }, + + # The general cache is what you get if you use our util.cache. It's used for + # things like caching the course.xml file for different A/B test groups. + # We set it to be a DummyCache to force reloading of course.xml in dev. + # In staging environments, we would grab VERSION from data uploaded by the + # push process. + 'general': { + 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', + 'KEY_PREFIX': 'general', + 'VERSION': 4, + 'KEY_FUNCTION': 'util.cache.memcache_safe_key', + } +} diff --git a/cms/manage.py b/cms/manage.py new file mode 100644 index 0000000000000000000000000000000000000000..3e4eedc9ff5862c99e999b544a5b34c4e9af877a --- /dev/null +++ b/cms/manage.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +from django.core.management import execute_manager +import imp +try: + imp.find_module('settings') # Assumed to be in the same directory. +except ImportError: + import sys + sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__) + sys.exit(1) + +import settings + +if __name__ == "__main__": + execute_manager(settings) diff --git a/lms/lib/util/__init__.py b/cms/models.py similarity index 100% rename from lms/lib/util/__init__.py rename to cms/models.py diff --git a/cms/templates/calendar.html b/cms/templates/calendar.html new file mode 100644 index 0000000000000000000000000000000000000000..05b2f888065e63369e65cff747cbe7b7befa09ad --- /dev/null +++ b/cms/templates/calendar.html @@ -0,0 +1,3 @@ +% for week in weeks: +${week} +% endfor diff --git a/cms/urls.py b/cms/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..80e2b19e9d32802acd72a12dc71e41611de364bd --- /dev/null +++ b/cms/urls.py @@ -0,0 +1,9 @@ +from django.conf.urls.defaults import patterns, url + +# Uncomment the next two lines to enable the admin: +# from django.contrib import admin +# admin.autodiscover() + +urlpatterns = patterns('cms.views', + url(r'^(?P<course>[^/]+)/calendar/', 'calendar', name='calendar'), +) diff --git a/cms/views.py b/cms/views.py new file mode 100644 index 0000000000000000000000000000000000000000..d0d4f4871cf5f1e84a2fb3db0cf3fde3d1c859fd --- /dev/null +++ b/cms/views.py @@ -0,0 +1,5 @@ +from mitxmako.shortcuts import render_to_response + + +def calendar(request, course): + return render_to_response('calendar.html', {}) diff --git a/common/djangoapps/track/__init__.py b/common/djangoapps/track/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/lms/djangoapps/track/middleware.py b/common/djangoapps/track/middleware.py similarity index 100% rename from lms/djangoapps/track/middleware.py rename to common/djangoapps/track/middleware.py diff --git a/lms/djangoapps/track/models.py b/common/djangoapps/track/models.py similarity index 100% rename from lms/djangoapps/track/models.py rename to common/djangoapps/track/models.py diff --git a/lms/djangoapps/track/tests.py b/common/djangoapps/track/tests.py similarity index 100% rename from lms/djangoapps/track/tests.py rename to common/djangoapps/track/tests.py diff --git a/lms/djangoapps/track/views.py b/common/djangoapps/track/views.py similarity index 100% rename from lms/djangoapps/track/views.py rename to common/djangoapps/track/views.py diff --git a/lms/lib/cache_toolbox/COPYING b/common/lib/cache_toolbox/COPYING similarity index 100% rename from lms/lib/cache_toolbox/COPYING rename to common/lib/cache_toolbox/COPYING diff --git a/lms/lib/cache_toolbox/README.rst b/common/lib/cache_toolbox/README.rst similarity index 100% rename from lms/lib/cache_toolbox/README.rst rename to common/lib/cache_toolbox/README.rst diff --git a/lms/lib/cache_toolbox/__init__.py b/common/lib/cache_toolbox/__init__.py similarity index 100% rename from lms/lib/cache_toolbox/__init__.py rename to common/lib/cache_toolbox/__init__.py diff --git a/lms/lib/cache_toolbox/app_settings.py b/common/lib/cache_toolbox/app_settings.py similarity index 100% rename from lms/lib/cache_toolbox/app_settings.py rename to common/lib/cache_toolbox/app_settings.py diff --git a/lms/lib/cache_toolbox/core.py b/common/lib/cache_toolbox/core.py similarity index 100% rename from lms/lib/cache_toolbox/core.py rename to common/lib/cache_toolbox/core.py diff --git a/lms/lib/cache_toolbox/middleware.py b/common/lib/cache_toolbox/middleware.py similarity index 100% rename from lms/lib/cache_toolbox/middleware.py rename to common/lib/cache_toolbox/middleware.py diff --git a/lms/lib/cache_toolbox/model.py b/common/lib/cache_toolbox/model.py similarity index 100% rename from lms/lib/cache_toolbox/model.py rename to common/lib/cache_toolbox/model.py diff --git a/lms/lib/cache_toolbox/relation.py b/common/lib/cache_toolbox/relation.py similarity index 100% rename from lms/lib/cache_toolbox/relation.py rename to common/lib/cache_toolbox/relation.py diff --git a/common/lib/cache_toolbox/templatetags/__init__.py b/common/lib/cache_toolbox/templatetags/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/lms/lib/cache_toolbox/templatetags/cache_toolbox.py b/common/lib/cache_toolbox/templatetags/cache_toolbox.py similarity index 100% rename from lms/lib/cache_toolbox/templatetags/cache_toolbox.py rename to common/lib/cache_toolbox/templatetags/cache_toolbox.py diff --git a/common/lib/monitoring/__init__.py b/common/lib/monitoring/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/common/lib/monitoring/exceptions.py b/common/lib/monitoring/exceptions.py new file mode 100644 index 0000000000000000000000000000000000000000..6a34d9a38f077a9ec999f653a668580ad8ed1499 --- /dev/null +++ b/common/lib/monitoring/exceptions.py @@ -0,0 +1,10 @@ +from django.core.signals import got_request_exception +from django.dispatch import receiver +import logging + + +@receiver(got_request_exception) +def record_request_exception(sender, **kwargs): + logging.exception("Uncaught exception from {sender}".format( + sender=sender + )) diff --git a/common/lib/util/__init__.py b/common/lib/util/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/lms/lib/util/cache.py b/common/lib/util/cache.py similarity index 100% rename from lms/lib/util/cache.py rename to common/lib/util/cache.py diff --git a/lms/lib/util/memcache.py b/common/lib/util/memcache.py similarity index 100% rename from lms/lib/util/memcache.py rename to common/lib/util/memcache.py diff --git a/lms/lib/util/middleware.py b/common/lib/util/middleware.py similarity index 100% rename from lms/lib/util/middleware.py rename to common/lib/util/middleware.py diff --git a/lms/lib/util/models.py b/common/lib/util/models.py similarity index 100% rename from lms/lib/util/models.py rename to common/lib/util/models.py diff --git a/lms/lib/util/tests.py b/common/lib/util/tests.py similarity index 100% rename from lms/lib/util/tests.py rename to common/lib/util/tests.py diff --git a/lms/lib/util/views.py b/common/lib/util/views.py similarity index 100% rename from lms/lib/util/views.py rename to common/lib/util/views.py diff --git a/lms/envs/common.py b/lms/envs/common.py index 806c379747f79e04adb2b372ab4f7b0a0d6febec..3ac026fd818390adf654fb40ac7e7cb01a913804 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -60,6 +60,7 @@ sys.path.append(ASKBOT_ROOT) sys.path.append(ASKBOT_ROOT / "askbot" / "deps") sys.path.append(PROJECT_ROOT / 'djangoapps') sys.path.append(PROJECT_ROOT / 'lib') +sys.path.append(COMMON_ROOT / 'djangoapps') sys.path.append(COMMON_ROOT / 'lib') ################################## MITXWEB ##################################### diff --git a/rakefile b/rakefile index 8f4966850602333b47f9b20fb48bb60eef22129c..6bd582783e64f6cbe57d668592ee7e6bbe1eda11 100644 --- a/rakefile +++ b/rakefile @@ -58,7 +58,7 @@ task :pylint => LMS_REPORT_DIR do end end -[:lms].each do |system| +[:lms, :cms].each do |system| task_name = "test_#{system}" report_dir = File.join(REPORT_DIR, task_name) directory report_dir @@ -69,6 +69,15 @@ end sh(django_admin(:lms, :test, 'test', *Dir['lms/djangoapps'].each)) end task :test => task_name + + desc <<-desc + Start the #{system} locally with the specified environment (defaults to dev). + Other useful environments are devplus (for dev testing with a real local database) + desc + task system, [:env, :options] => [] do |t, args| + args.with_defaults(:env => 'dev', :options => '') + sh(django_admin(system, args.env, 'runserver', args.options)) + end end Dir["common/lib/*"].each do |lib| @@ -85,15 +94,6 @@ Dir["common/lib/*"].each do |lib| task :test => task_name end -desc <<-desc - Start the lms locally with the specified environment (defaults to dev). - Other useful environments are devplus (for dev testing with a real local database) - desc -task :lms, [:env] => [] do |t, args| - args.with_defaults(:env => 'dev') - sh(django_admin(:lms, args.env, 'runserver')) -end - task :runserver => :lms desc "Run django-admin <action> against the specified system and environment"