From ed114e15106192b22ebb78ef5bf5bce72b419d13 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Wed, 13 Jul 2005 01:25:57 +0000 Subject: [PATCH] Imported Django from private SVN repository (created from r. 8825) git-svn-id: http://code.djangoproject.com/svn/django/trunk@3 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/__init__.py | 0 django/bin/__init__.py | 0 django/bin/daily_cleanup.py | 15 + django/bin/django-admin.py | 412 ++++ django/bin/profiling/__init__.py | 0 django/bin/profiling/gather_profile_stats.py | 34 + django/bin/profiling/handler.py | 22 + django/bin/setup.py | 45 + django/bin/validate.py | 36 + django/conf/__init__.py | 0 django/conf/app_template/__init__.py | 0 django/conf/app_template/models/__init__.py | 1 + django/conf/app_template/models/app_name.py | 3 + django/conf/app_template/urls/__init__.py | 0 django/conf/app_template/urls/app_name.py | 5 + django/conf/app_template/views/__init__.py | 0 django/conf/global_settings.py | 199 ++ django/conf/project_template/__init__.py | 0 django/conf/project_template/apps/__init__.py | 0 .../project_template/settings/__init__.py | 0 django/conf/project_template/settings/main.py | 31 + django/conf/settings.py | 42 + django/conf/urls/__init__.py | 0 django/conf/urls/admin.py | 56 + django/conf/urls/admin_password_reset.py | 6 + django/conf/urls/comments.py | 12 + django/conf/urls/defaults.py | 17 + django/conf/urls/flatfiles.py | 5 + django/conf/urls/registration.py | 19 + django/conf/urls/rss.py | 6 + django/conf/urls/shortcut.py | 5 + django/core/__init__.py | 0 django/core/cache.py | 255 ++ django/core/db/__init__.py | 28 + django/core/db/backends/__init__.py | 0 django/core/db/backends/mysql.py | 107 + django/core/db/backends/postgresql.py | 109 + django/core/db/base.py | 32 + django/core/db/typecasts.py | 42 + django/core/defaultfilters.py | 466 ++++ django/core/defaulttags.py | 743 ++++++ django/core/exceptions.py | 26 + django/core/extensions.py | 79 + django/core/formfields.py | 759 ++++++ django/core/handler.py | 157 ++ django/core/mail.py | 51 + django/core/meta.py | 2142 +++++++++++++++++ django/core/paginator.py | 76 + django/core/rss.py | 136 ++ django/core/template.py | 488 ++++ django/core/template_file.py | 18 + django/core/template_loader.py | 142 ++ django/core/urlresolvers.py | 96 + django/core/validators.py | 420 ++++ django/core/xheaders.py | 22 + django/middleware/__init__.py | 0 django/middleware/admin.py | 120 + django/middleware/common.py | 104 + django/middleware/doc.py | 18 + django/models/__init__.py | 91 + django/models/auth.py | 290 +++ django/models/comments.py | 281 +++ django/models/core.py | 107 + django/parts/__init__.py | 0 django/parts/admin/__init__.py | 0 django/parts/admin/doc.py | 93 + django/parts/auth/__init__.py | 0 django/parts/auth/anonymoususers.py | 48 + django/parts/auth/formfields.py | 46 + django/parts/media/__init__.py | 0 django/parts/media/photos.py | 6 + django/templatetags/__init__.py | 7 + django/templatetags/comments.py | 331 +++ django/templatetags/log.py | 45 + django/tests/__init__.py | 0 django/tests/cache_tests.py | 119 + django/tests/template_inheritance.py | 102 + django/tests/template_tests.py | 707 ++++++ django/utils/__init__.py | 0 django/utils/datastructures.py | 171 ++ django/utils/dateformat.py | 317 +++ django/utils/dates.py | 27 + django/utils/feedgenerator.py | 152 ++ django/utils/html.py | 110 + django/utils/httpwrappers.py | 319 +++ django/utils/images.py | 22 + django/utils/stopwords.py | 42 + django/utils/text.py | 108 + django/utils/timesince.py | 46 + django/utils/xmlutils.py | 13 + django/views/__init__.py | 0 django/views/admin/__init__.py | 0 django/views/admin/doc.py | 328 +++ django/views/admin/main.py | 1089 +++++++++ django/views/admin/template.py | 70 + django/views/auth/__init__.py | 0 django/views/auth/login.py | 62 + django/views/comments/__init__.py | 0 django/views/comments/comments.py | 347 +++ django/views/comments/karma.py | 34 + django/views/comments/userflags.py | 82 + django/views/core/__init__.py | 0 django/views/core/flatfiles.py | 34 + django/views/decorators/__init__.py | 0 django/views/decorators/auth.py | 12 + django/views/decorators/cache.py | 64 + django/views/defaults.py | 72 + django/views/generic/__init__.py | 0 django/views/generic/date_based.py | 223 ++ django/views/generic/list_detail.py | 106 + django/views/registration/__init__.py | 0 django/views/registration/passwords.py | 109 + django/views/rss/__init__.py | 0 django/views/rss/rss.py | 12 + 114 files changed, 13851 insertions(+) create mode 100644 django/__init__.py create mode 100644 django/bin/__init__.py create mode 100644 django/bin/daily_cleanup.py create mode 100644 django/bin/django-admin.py create mode 100644 django/bin/profiling/__init__.py create mode 100644 django/bin/profiling/gather_profile_stats.py create mode 100644 django/bin/profiling/handler.py create mode 100644 django/bin/setup.py create mode 100644 django/bin/validate.py create mode 100644 django/conf/__init__.py create mode 100644 django/conf/app_template/__init__.py create mode 100644 django/conf/app_template/models/__init__.py create mode 100644 django/conf/app_template/models/app_name.py create mode 100644 django/conf/app_template/urls/__init__.py create mode 100644 django/conf/app_template/urls/app_name.py create mode 100644 django/conf/app_template/views/__init__.py create mode 100644 django/conf/global_settings.py create mode 100644 django/conf/project_template/__init__.py create mode 100644 django/conf/project_template/apps/__init__.py create mode 100644 django/conf/project_template/settings/__init__.py create mode 100644 django/conf/project_template/settings/main.py create mode 100644 django/conf/settings.py create mode 100644 django/conf/urls/__init__.py create mode 100644 django/conf/urls/admin.py create mode 100644 django/conf/urls/admin_password_reset.py create mode 100644 django/conf/urls/comments.py create mode 100644 django/conf/urls/defaults.py create mode 100644 django/conf/urls/flatfiles.py create mode 100644 django/conf/urls/registration.py create mode 100644 django/conf/urls/rss.py create mode 100644 django/conf/urls/shortcut.py create mode 100644 django/core/__init__.py create mode 100644 django/core/cache.py create mode 100644 django/core/db/__init__.py create mode 100644 django/core/db/backends/__init__.py create mode 100644 django/core/db/backends/mysql.py create mode 100644 django/core/db/backends/postgresql.py create mode 100644 django/core/db/base.py create mode 100644 django/core/db/typecasts.py create mode 100644 django/core/defaultfilters.py create mode 100644 django/core/defaulttags.py create mode 100644 django/core/exceptions.py create mode 100644 django/core/extensions.py create mode 100644 django/core/formfields.py create mode 100644 django/core/handler.py create mode 100644 django/core/mail.py create mode 100644 django/core/meta.py create mode 100644 django/core/paginator.py create mode 100644 django/core/rss.py create mode 100644 django/core/template.py create mode 100644 django/core/template_file.py create mode 100644 django/core/template_loader.py create mode 100644 django/core/urlresolvers.py create mode 100644 django/core/validators.py create mode 100644 django/core/xheaders.py create mode 100644 django/middleware/__init__.py create mode 100644 django/middleware/admin.py create mode 100644 django/middleware/common.py create mode 100644 django/middleware/doc.py create mode 100644 django/models/__init__.py create mode 100644 django/models/auth.py create mode 100644 django/models/comments.py create mode 100644 django/models/core.py create mode 100644 django/parts/__init__.py create mode 100644 django/parts/admin/__init__.py create mode 100644 django/parts/admin/doc.py create mode 100644 django/parts/auth/__init__.py create mode 100644 django/parts/auth/anonymoususers.py create mode 100644 django/parts/auth/formfields.py create mode 100644 django/parts/media/__init__.py create mode 100644 django/parts/media/photos.py create mode 100644 django/templatetags/__init__.py create mode 100644 django/templatetags/comments.py create mode 100644 django/templatetags/log.py create mode 100644 django/tests/__init__.py create mode 100644 django/tests/cache_tests.py create mode 100644 django/tests/template_inheritance.py create mode 100644 django/tests/template_tests.py create mode 100644 django/utils/__init__.py create mode 100644 django/utils/datastructures.py create mode 100644 django/utils/dateformat.py create mode 100644 django/utils/dates.py create mode 100644 django/utils/feedgenerator.py create mode 100644 django/utils/html.py create mode 100644 django/utils/httpwrappers.py create mode 100644 django/utils/images.py create mode 100644 django/utils/stopwords.py create mode 100644 django/utils/text.py create mode 100644 django/utils/timesince.py create mode 100644 django/utils/xmlutils.py create mode 100644 django/views/__init__.py create mode 100644 django/views/admin/__init__.py create mode 100644 django/views/admin/doc.py create mode 100644 django/views/admin/main.py create mode 100644 django/views/admin/template.py create mode 100644 django/views/auth/__init__.py create mode 100644 django/views/auth/login.py create mode 100644 django/views/comments/__init__.py create mode 100644 django/views/comments/comments.py create mode 100644 django/views/comments/karma.py create mode 100644 django/views/comments/userflags.py create mode 100644 django/views/core/__init__.py create mode 100644 django/views/core/flatfiles.py create mode 100644 django/views/decorators/__init__.py create mode 100644 django/views/decorators/auth.py create mode 100644 django/views/decorators/cache.py create mode 100644 django/views/defaults.py create mode 100644 django/views/generic/__init__.py create mode 100644 django/views/generic/date_based.py create mode 100644 django/views/generic/list_detail.py create mode 100644 django/views/registration/__init__.py create mode 100644 django/views/registration/passwords.py create mode 100644 django/views/rss/__init__.py create mode 100644 django/views/rss/rss.py diff --git a/django/__init__.py b/django/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/bin/__init__.py b/django/bin/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/bin/daily_cleanup.py b/django/bin/daily_cleanup.py new file mode 100644 index 0000000000..b7235cd10c --- /dev/null +++ b/django/bin/daily_cleanup.py @@ -0,0 +1,15 @@ +"Daily cleanup file" + +from django.core.db import db + +DOCUMENTATION_DIRECTORY = '/home/html/documentation/' + +def clean_up(): + # Clean up old database records + cursor = db.cursor() + cursor.execute("DELETE FROM auth_sessions WHERE start_time < NOW() - INTERVAL '2 weeks'") + cursor.execute("DELETE FROM registration_challenges WHERE request_date < NOW() - INTERVAL '1 week'") + db.commit() + +if __name__ == "__main__": + clean_up() diff --git a/django/bin/django-admin.py b/django/bin/django-admin.py new file mode 100644 index 0000000000..fd2d96ad28 --- /dev/null +++ b/django/bin/django-admin.py @@ -0,0 +1,412 @@ +#!/usr/bin/python2.3 +from django.core import db, meta +import django +import os, re, sys + +MODULE_TEMPLATE = ''' {%% if perms.%(app)s.%(addperm)s or perms.%(app)s.%(changeperm)s %%} + + {%% if perms.%(app)s.%(changeperm)s %%}{%% endif %%}%(name)s{%% if perms.%(app)s.%(changeperm)s %%}{%% endif %%} + {%% if perms.%(app)s.%(addperm)s %%}{%% endif %%}Add{%% if perms.%(app)s.%(addperm)s %%}{%% endif %%} + {%% if perms.%(app)s.%(changeperm)s %%}{%% endif %%}Change{%% if perms.%(app)s.%(changeperm)s %%}{%% endif %%} + + {%% endif %%}''' + +APP_ARGS = '[app app ...]' + +PROJECT_TEMPLATE_DIR = django.__path__[0] + '/conf/%s_template' + +def _get_packages_insert(app_label): + return "INSERT INTO packages (label, name) VALUES ('%s', '%s');" % (app_label, app_label) + +def _get_permission_codename(action, opts): + return '%s_%s' % (action, opts.object_name.lower()) + +def _get_all_permissions(opts): + "Returns (codename, name) for all permissions in the given opts." + perms = [] + if opts.admin: + for action in ('add', 'change', 'delete'): + perms.append((_get_permission_codename(action, opts), 'Can %s %s' % (action, opts.verbose_name))) + return perms + list(opts.permissions) + +def _get_permission_insert(name, codename, opts): + return "INSERT INTO auth_permissions (name, package, codename) VALUES ('%s', '%s', '%s');" % \ + (name.replace("'", "''"), opts.app_label, codename) + +def _get_contenttype_insert(opts): + return "INSERT INTO content_types (name, package, python_module_name) VALUES ('%s', '%s', '%s');" % \ + (opts.verbose_name, opts.app_label, opts.module_name) + +def _is_valid_dir_name(s): + return bool(re.search(r'^\w+$', s)) + +def get_sql_create(mod): + "Returns a list of the CREATE TABLE SQL statements for the given module." + final_output = [] + for klass in mod._MODELS: + opts = klass._meta + table_output = [] + for f in opts.fields: + if isinstance(f, meta.ForeignKey): + rel_field = f.rel.to.get_field(f.rel.field_name) + # If the foreign key points to an AutoField, the foreign key + # should be an IntegerField, not an AutoField. Otherwise, the + # foreign key should be the same type of field as the field + # to which it points. + if rel_field.__class__.__name__ == 'AutoField': + data_type = 'IntegerField' + else: + rel_field.__class__.__name__ + else: + rel_field = f + data_type = f.__class__.__name__ + col_type = db.DATA_TYPES[data_type] + if col_type is not None: + field_output = [f.name, col_type % rel_field.__dict__] + field_output.append('%sNULL' % (not f.null and 'NOT ' or '')) + if f.unique: + field_output.append('UNIQUE') + if f.primary_key: + field_output.append('PRIMARY KEY') + if f.rel: + field_output.append('REFERENCES %s (%s)' % \ + (f.rel.to.db_table, f.rel.to.get_field(f.rel.field_name).name)) + table_output.append(' '.join(field_output)) + if opts.order_with_respect_to: + table_output.append('_order %s NULL' % db.DATA_TYPES['IntegerField']) + for field_constraints in opts.unique_together: + table_output.append('UNIQUE (%s)' % ", ".join(field_constraints)) + + full_statement = ['CREATE TABLE %s (' % opts.db_table] + for i, line in enumerate(table_output): # Combine and add commas. + full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or '')) + full_statement.append(');') + final_output.append('\n'.join(full_statement)) + + for klass in mod._MODELS: + opts = klass._meta + for f in opts.many_to_many: + table_output = ['CREATE TABLE %s_%s (' % (opts.db_table, f.name)] + table_output.append(' id %s NOT NULL PRIMARY KEY,' % db.DATA_TYPES['AutoField']) + table_output.append(' %s_id %s NOT NULL REFERENCES %s (%s),' % \ + (opts.object_name.lower(), db.DATA_TYPES['IntegerField'], opts.db_table, opts.pk.name)) + table_output.append(' %s_id %s NOT NULL REFERENCES %s (%s),' % \ + (f.rel.to.object_name.lower(), db.DATA_TYPES['IntegerField'], f.rel.to.db_table, f.rel.to.pk.name)) + table_output.append(' UNIQUE (%s_id, %s_id)' % (opts.object_name.lower(), f.rel.to.object_name.lower())) + table_output.append(');') + final_output.append('\n'.join(table_output)) + return final_output +get_sql_create.help_doc = "Prints the CREATE TABLE SQL statements for the given app(s)." +get_sql_create.args = APP_ARGS + +def get_sql_delete(mod): + "Returns a list of the DROP TABLE SQL statements for the given module." + try: + cursor = db.db.cursor() + except: + cursor = None + output = [] + for klass in mod._MODELS: + try: + if cursor is not None: + # Check whether the table exists. + cursor.execute("SELECT 1 FROM %s LIMIT 1" % klass._meta.db_table) + except: + # The table doesn't exist, so it doesn't need to be dropped. + pass + else: + output.append("DROP TABLE %s;" % klass._meta.db_table) + for klass in mod._MODELS: + opts = klass._meta + for f in opts.many_to_many: + try: + if cursor is not None: + cursor.execute("SELECT 1 FROM %s_%s LIMIT 1" % (opts.db_table, f.name)) + except: + pass + else: + output.append("DROP TABLE %s_%s;" % (opts.db_table, f.name)) + output.append("DELETE FROM packages WHERE label = '%s';" % mod._MODELS[0]._meta.app_label) + return output +get_sql_delete.help_doc = "Prints the DROP TABLE SQL statements for the given app(s)." +get_sql_delete.args = APP_ARGS + +def get_sql_reset(mod): + "Returns a list of the DROP TABLE SQL, then the CREATE TABLE SQL, for the given module." + return get_sql_delete(mod) + get_sql_all(mod) +get_sql_reset.help_doc = "Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app(s)." +get_sql_reset.args = APP_ARGS + +def get_sql_initial_data(mod): + "Returns a list of the initial INSERT SQL statements for the given module." + output = [] + app_label = mod._MODELS[0]._meta.app_label + output.append(_get_packages_insert(app_label)) + app_dir = os.path.normpath(os.path.join(os.path.dirname(mod.__file__), '../sql')) + for klass in mod._MODELS: + opts = klass._meta + # Add custom SQL, if it's available. + sql_file_name = os.path.join(app_dir, opts.module_name + '.sql') + if os.path.exists(sql_file_name): + fp = open(sql_file_name, 'r') + output.append(fp.read()) + fp.close() + # Content types. + output.append(_get_contenttype_insert(opts)) + # Permissions. + for codename, name in _get_all_permissions(opts): + output.append(_get_permission_insert(name, codename, opts)) + return output +get_sql_initial_data.help_doc = "Prints the initial INSERT SQL statements for the given app(s)." +get_sql_initial_data.args = APP_ARGS + +def get_sql_sequence_reset(mod): + "Returns a list of the SQL statements to reset PostgreSQL sequences for the given module." + output = [] + for klass in mod._MODELS: + for f in klass._meta.fields: + if isinstance(f, meta.AutoField): + output.append("SELECT setval('%s_%s_seq', (SELECT max(%s) FROM %s));" % (klass._meta.db_table, f.name, f.name, klass._meta.db_table)) + return output +get_sql_sequence_reset.help_doc = "Prints the SQL statements for resetting PostgreSQL sequences for the given app(s)." +get_sql_sequence_reset.args = APP_ARGS + +def get_sql_indexes(mod): + "Returns a list of the CREATE INDEX SQL statements for the given module." + output = [] + for klass in mod._MODELS: + for f in klass._meta.fields: + if f.db_index: + unique = f.unique and "UNIQUE " or "" + output.append("CREATE %sINDEX %s_%s ON %s (%s);" % \ + (unique, klass._meta.db_table, f.name, klass._meta.db_table, f.name)) + return output +get_sql_indexes.help_doc = "Prints the CREATE INDEX SQL statements for the given app(s)." +get_sql_indexes.args = APP_ARGS + +def get_sql_all(mod): + "Returns a list of CREATE TABLE SQL and initial-data insert for the given module." + return get_sql_create(mod) + get_sql_initial_data(mod) +get_sql_all.help_doc = "Prints the CREATE TABLE and initial-data SQL statements for the given app(s)." +get_sql_all.args = APP_ARGS + +def database_check(mod): + "Checks that everything is properly installed in the database for the given module." + cursor = db.db.cursor() + app_label = mod._MODELS[0]._meta.app_label + + # Check that the package exists in the database. + cursor.execute("SELECT 1 FROM packages WHERE label = %s", [app_label]) + if cursor.rowcount < 1: +# sys.stderr.write("The '%s' package isn't installed.\n" % app_label) + print _get_packages_insert(app_label) + + # Check that the permissions and content types are in the database. + perms_seen = {} + contenttypes_seen = {} + for klass in mod._MODELS: + opts = klass._meta + perms = _get_all_permissions(opts) + perms_seen.update(dict(perms)) + contenttypes_seen[opts.module_name] = 1 + for codename, name in perms: + cursor.execute("SELECT 1 FROM auth_permissions WHERE package = %s AND codename = %s", (app_label, codename)) + if cursor.rowcount < 1: +# sys.stderr.write("The '%s.%s' permission doesn't exist.\n" % (app_label, codename)) + print _get_permission_insert(name, codename, opts) + cursor.execute("SELECT 1 FROM content_types WHERE package = %s AND python_module_name = %s", (app_label, opts.module_name)) + if cursor.rowcount < 1: +# sys.stderr.write("The '%s.%s' content type doesn't exist.\n" % (app_label, opts.module_name)) + print _get_contenttype_insert(opts) + + # Check that there aren't any *extra* permissions in the DB that the model + # doesn't know about. + cursor.execute("SELECT codename FROM auth_permissions WHERE package = %s", (app_label,)) + for row in cursor.fetchall(): + try: + perms_seen[row[0]] + except KeyError: +# sys.stderr.write("A permission called '%s.%s' was found in the database but not in the model.\n" % (app_label, row[0])) + print "DELETE FROM auth_permissions WHERE package='%s' AND codename = '%s';" % (app_label, row[0]) + + # Check that there aren't any *extra* content types in the DB that the + # model doesn't know about. + cursor.execute("SELECT python_module_name FROM content_types WHERE package = %s", (app_label,)) + for row in cursor.fetchall(): + try: + contenttypes_seen[row[0]] + except KeyError: +# sys.stderr.write("A content type called '%s.%s' was found in the database but not in the model.\n" % (app_label, row[0])) + print "DELETE FROM content_types WHERE package='%s' AND python_module_name = '%s';" % (app_label, row[0]) +database_check.help_doc = "Checks that everything is installed in the database for the given app(s) and prints SQL statements if needed." +database_check.args = APP_ARGS + +def get_admin_index(mod): + "Returns admin-index template snippet (in list form) for the given module." + output = [] + app_label = mod._MODELS[0]._meta.app_label + output.append('{%% if perms.%s %%}' % app_label) + output.append('

%s

' % app_label.title()) + for klass in mod._MODELS: + if klass._meta.admin: + output.append(MODULE_TEMPLATE % { + 'app': app_label, + 'mod': klass._meta.module_name, + 'name': meta.capfirst(klass._meta.verbose_name_plural), + 'addperm': klass._meta.get_add_permission(), + 'changeperm': klass._meta.get_change_permission(), + }) + output.append('
') + output.append('{% endif %}') + return output +get_admin_index.help_doc = "Prints the admin-index template snippet for the given app(s)." +get_admin_index.args = APP_ARGS + +def init(): + "Initializes the database with auth and core." + auth = meta.get_app('auth') + core = meta.get_app('core') + try: + cursor = db.db.cursor() + for sql in get_sql_create(core) + get_sql_create(auth) + get_sql_initial_data(core) + get_sql_initial_data(auth): + cursor.execute(sql) + except Exception, e: + sys.stderr.write("Error: The database couldn't be initialized. Here's the full exception:\n%s\n" % e) + db.db.rollback() + sys.exit(1) + db.db.commit() +init.args = '' + +def install(mod): + "Executes the equivalent of 'get_sql_all' in the current database." + sql_list = get_sql_all(mod) + try: + cursor = db.db.cursor() + for sql in sql_list: + cursor.execute(sql) + except Exception, e: + mod_name = mod.__name__[mod.__name__.rindex('.')+1:] + sys.stderr.write("""Error: %s couldn't be installed. Possible reasons: + * The database isn't running or isn't configured correctly. + * At least one of the database tables already exists. + * The SQL was invalid. +Hint: Look at the output of '%s sqlall %s'. That's the SQL this command wasn't able to run. +The full error: %s\n""" % \ + (mod_name, __file__, mod_name, e)) + db.db.rollback() + sys.exit(1) + db.db.commit() +install.args = APP_ARGS + +def _start_helper(app_or_project, name, directory, other_name=''): + other = {'project': 'app', 'app': 'project'}[app_or_project] + if not _is_valid_dir_name(name): + sys.stderr.write("Error: %r is not a valid %s name. Please use only numbers, letters and underscores.\n" % (name, app_or_project)) + sys.exit(1) + top_dir = os.path.join(directory, name) + try: + os.mkdir(top_dir) + except OSError, e: + sys.stderr.write("Error: %s\n" % e) + sys.exit(1) + template_dir = PROJECT_TEMPLATE_DIR % app_or_project + for d, subdirs, files in os.walk(template_dir): + relative_dir = d[len(template_dir)+1:].replace('%s_name' % app_or_project, name) + if relative_dir: + os.mkdir(os.path.join(top_dir, relative_dir)) + for f in files: + fp_old = open(os.path.join(d, f), 'r') + fp_new = open(os.path.join(top_dir, relative_dir, f.replace('%s_name' % app_or_project, name)), 'w') + fp_new.write(fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name)) + fp_old.close() + fp_new.close() + +def startproject(project_name, directory): + "Creates a Django project for the given project_name in the given directory." + _start_helper('project', project_name, directory) +startproject.help_doc = "Creates a Django project directory structure for the given project name in the current directory." +startproject.args = "[projectname]" + +def startapp(app_name, directory): + "Creates a Django app for the given project_name in the given directory." + # Determine the project_name a bit naively -- by looking at the name of + # the parent directory. + project_dir = os.path.normpath(os.path.join(directory, '../')) + project_name = os.path.basename(project_dir) + _start_helper('app', app_name, directory, project_name) + settings_file = os.path.join(project_dir, 'settings/main.py') + if os.path.exists(settings_file): + try: + settings_contents = open(settings_file, 'r').read() + fp = open(settings_file, 'w') + except IOError: + pass + else: + settings_contents = re.sub(r'(?s)\b(INSTALLED_APPS\s*=\s*\()(.*?)\)', "\\1\n '%s',\\2)" % app_name, settings_contents) + fp.write(settings_contents) + fp.close() +startapp.help_doc = "Creates a Django app directory structure for the given app name in the current directory." +startapp.args = "[appname]" + +def usage(): + sys.stderr.write("Usage: %s [action]\n" % sys.argv[0]) + + available_actions = ACTION_MAPPING.keys() + available_actions.sort() + sys.stderr.write("Available actions:\n") + for a in available_actions: + func = ACTION_MAPPING[a] + sys.stderr.write(" %s %s-- %s\n" % (a, func.args, getattr(func, 'help_doc', func.__doc__))) + sys.exit(1) + +ACTION_MAPPING = { + 'adminindex': get_admin_index, +# 'dbcheck': database_check, + 'sql': get_sql_create, + 'sqlall': get_sql_all, + 'sqlclear': get_sql_delete, + 'sqlindexes': get_sql_indexes, + 'sqlinitialdata': get_sql_initial_data, + 'sqlreset': get_sql_reset, + 'sqlsequencereset': get_sql_sequence_reset, + 'startapp': startapp, + 'startproject': startproject, + 'init': init, + 'install': install, +} + +if __name__ == "__main__": + try: + action = sys.argv[1] + except IndexError: + usage() + if not ACTION_MAPPING.has_key(action): + usage() + if action == 'init': + init() + sys.exit(0) + elif action in ('startapp', 'startproject'): + try: + name = sys.argv[2] + except IndexError: + usage() + ACTION_MAPPING[action](name, os.getcwd()) + sys.exit(0) + elif action == 'dbcheck': + mod_list = meta.get_all_installed_modules() + else: + try: + mod_list = [meta.get_app(app_label) for app_label in sys.argv[2:]] + except ImportError, e: + sys.stderr.write("Error: %s. Are you sure your INSTALLED_APPS setting is correct?\n" % e) + sys.exit(1) + if not mod_list: + usage() + if action not in ('adminindex', 'dbcheck', 'install', 'sqlindexes'): + print "BEGIN;" + for mod in mod_list: + output = ACTION_MAPPING[action](mod) + if output: + print '\n'.join(output) + if action not in ('adminindex', 'dbcheck', 'install', 'sqlindexes'): + print "COMMIT;" diff --git a/django/bin/profiling/__init__.py b/django/bin/profiling/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/bin/profiling/gather_profile_stats.py b/django/bin/profiling/gather_profile_stats.py new file mode 100644 index 0000000000..852f16229d --- /dev/null +++ b/django/bin/profiling/gather_profile_stats.py @@ -0,0 +1,34 @@ +""" +gather_profile_stats.py /path/to/dir/of/profiles + +Note that the aggregated profiles must be read with pstats.Stats, not +hotshot.stats (the formats are incompatible) +""" + +from hotshot import stats +import pstats +import sys, os + +def gather_stats(p): + profiles = {} + for f in os.listdir(p): + if f.endswith('.agg.prof'): + path = f[:-9] + prof = pstats.Stats(os.path.join(p, f)) + elif f.endswith('.prof'): + bits = f.split('.') + path = ".".join(bits[:-3]) + prof = stats.load(os.path.join(p, f)) + else: + continue + print "Processing %s" % f + if profiles.has_key(path): + profiles[path].add(prof) + else: + profiles[path] = prof + os.unlink(os.path.join(p, f)) + for (path, prof) in profiles.items(): + prof.dump_stats(os.path.join(p, "%s.agg.prof" % path)) + +if __name__ == '__main__': + gather_stats(sys.argv[1]) diff --git a/django/bin/profiling/handler.py b/django/bin/profiling/handler.py new file mode 100644 index 0000000000..8a7512b079 --- /dev/null +++ b/django/bin/profiling/handler.py @@ -0,0 +1,22 @@ +import hotshot, time, os +from django.core.handler import CoreHandler + +PROFILE_DATA_DIR = "/var/log/cmsprofile/" + +def handler(req): + ''' + Handler that uses hotshot to store profile data. + + Stores profile data in PROFILE_DATA_DIR. Since hotshot has no way (that I + know of) to append profile data to a single file, each request gets its own + profile. The file names are in the format ..prof where is + the request path with "/" replaced by ".", and is a timestamp with + microseconds to prevent overwriting files. + + Use the gather_profile_stats.py script to gather these individual request + profiles into aggregated profiles by request path. + ''' + profname = "%s.%.3f.prof" % (req.uri.strip("/").replace('/', '.'), time.time()) + profname = os.path.join(PROFILE_DATA_DIR, profname) + prof = hotshot.Profile(profname) + return prof.runcall(CoreHandler(), req) diff --git a/django/bin/setup.py b/django/bin/setup.py new file mode 100644 index 0000000000..086be541a0 --- /dev/null +++ b/django/bin/setup.py @@ -0,0 +1,45 @@ +""" +Usage: + +python setup.py bdist +python setup.py sdist +""" + +from distutils.core import setup +import os + +# Whether to include the .py files, rather than just .pyc's. Doesn't do anything yet. +INCLUDE_SOURCE = True + +# Determines which apps are bundled with the distribution. +INSTALLED_APPS = ('auth', 'categories', 'comments', 'core', 'media', 'news', 'polls', 'registration', 'search', 'sms', 'staff') + +# First, lump together all the generic, core packages that need to be included. +packages = [ + 'django', + 'django.core', + 'django.templatetags', + 'django.utils', + 'django.views', +] +for a in INSTALLED_APPS: + for dirname in ('parts', 'templatetags', 'views'): + if os.path.exists('django/%s/%s/' % (dirname, a)): + packages.append('django.%s.%s' % (dirname, a)) + +# Next, add individual modules. +py_modules = [ + 'django.cron.daily_cleanup', + 'django.cron.search_indexer', +] +py_modules += ['django.models.%s' % a for a in INSTALLED_APPS] + +setup( + name = 'django', + version = '1.0', + packages = packages, + py_modules = py_modules, + url = 'http://www.ljworld.com/', + author = 'World Online', + author_email = 'cms-support@ljworld.com', +) diff --git a/django/bin/validate.py b/django/bin/validate.py new file mode 100644 index 0000000000..f0c37d01cb --- /dev/null +++ b/django/bin/validate.py @@ -0,0 +1,36 @@ +from django.core import meta + +def validate_app(app_label): + mod = meta.get_app(app_label) + for klass in mod._MODELS: + try: + validate_class(klass) + except AssertionError, e: + print e + +def validate_class(klass): + opts = klass._meta + # Fields. + for f in opts.fields: + if isinstance(f, meta.ManyToManyField): + assert isinstance(f.rel, meta.ManyToMany), "ManyToManyField %s should have 'rel' set to a ManyToMany instance." % f.name + # Inline related objects. + for rel_opts, rel_field in opts.get_inline_related_objects(): + assert len([f for f in rel_opts.fields if f.core]) > 0, "At least one field in %s should have core=True, because it's being edited inline by %s." % (rel_opts.object_name, opts.object_name) + # All related objects. + related_apps_seen = [] + for rel_opts, rel_field in opts.get_all_related_objects(): + if rel_opts in related_apps_seen: + assert rel_field.rel.related_name is not None, "Relationship in field %s.%s needs to set 'related_name' because more than one %s object is referenced in %s." % (rel_opts.object_name, rel_field.name, opts.object_name, rel_opts.object_name) + related_apps_seen.append(rel_opts) + # Etc. + if opts.admin is not None: + assert opts.admin.ordering or opts.ordering, "%s needs to set 'ordering' on either its 'admin' or its model, because it has 'admin' set." % opts.object_name + +if __name__ == "__main__": + import sys + try: + validate_app(sys.argv[1]) + except IndexError: + sys.stderr.write("Usage: %s [appname]\n" % __file__) + sys.exit(1) diff --git a/django/conf/__init__.py b/django/conf/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/app_template/__init__.py b/django/conf/app_template/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/app_template/models/__init__.py b/django/conf/app_template/models/__init__.py new file mode 100644 index 0000000000..502a7d0738 --- /dev/null +++ b/django/conf/app_template/models/__init__.py @@ -0,0 +1 @@ +__all__ = ['{{ app_name }}'] diff --git a/django/conf/app_template/models/app_name.py b/django/conf/app_template/models/app_name.py new file mode 100644 index 0000000000..6fce302e01 --- /dev/null +++ b/django/conf/app_template/models/app_name.py @@ -0,0 +1,3 @@ +from django.core import meta + +# Create your models here. diff --git a/django/conf/app_template/urls/__init__.py b/django/conf/app_template/urls/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/app_template/urls/app_name.py b/django/conf/app_template/urls/app_name.py new file mode 100644 index 0000000000..de814a56d1 --- /dev/null +++ b/django/conf/app_template/urls/app_name.py @@ -0,0 +1,5 @@ +from django.conf.urls.defaults import * + +urlpatterns = patterns('{{ project_name }}.apps.{{ app_name }}.views', +# (r'', ''), +) diff --git a/django/conf/app_template/views/__init__.py b/django/conf/app_template/views/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py new file mode 100644 index 0000000000..871ef95a93 --- /dev/null +++ b/django/conf/global_settings.py @@ -0,0 +1,199 @@ +# Default Django settings. Override these with settings in the module +# pointed-to by the DJANGO_SETTINGS_MODULE environment variable. + +import re + +#################### +# CORE # +#################### + +DEBUG = False + +# Whether to use the "Etag" header. This saves bandwidth but slows down performance. +USE_ETAGS = False + +# people who get code error notifications +ADMINS = (('Adrian Holovaty','aholovaty@ljworld.com'), ('Jacob Kaplan-Moss', 'jacob@lawrence.com')) + +# These IP addresses: +# * See debug comments, when DEBUG is true +# * Receive x-headers +INTERNAL_IPS = ( + '24.124.4.220', # World Online offices + '24.124.1.4', # https://admin.6newslawrence.com/ + '24.148.30.138', # Adrian home + '127.0.0.1', # localhost +) + +# Local time zone for this installation. All choices can be found here: +# http://www.postgresql.org/docs/current/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE +TIME_ZONE = 'America/Chicago' + +# Language code for this installation. All choices can be found here: +# http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes +# http://blogs.law.harvard.edu/tech/stories/storyReader$15 +LANGUAGE_CODE = 'en-us' + +# Not-necessarily-technical managers of the site. They get broken link +# notifications and other various e-mails. +MANAGERS = ADMINS + +# which e-mail address error messages come from +SERVER_EMAIL = None + +# Whether to send broken-link e-mails +SEND_BROKEN_LINK_EMAILS = True + +# postgres database connection info +DATABASE_ENGINE = 'postgresql' +DATABASE_NAME = 'cms' +DATABASE_USER = 'apache' +DATABASE_PASSWORD = '' +DATABASE_HOST = '' # set to empty string for localhost + +# host for sending e-mail +EMAIL_HOST = 'localhost' + +# name of the session cookie +AUTH_SESSION_COOKIE = 'rizzo' + +# name of the authorization profile module (below django.apps) +AUTH_PROFILE_MODULE = '' + +# list of locations of the template source files, in search order +TEMPLATE_DIRS = [] + +# default e-mail address to use for various automated correspondence from the site managers +DEFAULT_FROM_EMAIL = 'webmaster@ljworld.com' + +# whether to append trailing slashes to URLs +APPEND_SLASH = True + +# whether to prepend the "www." subdomain to URLs +PREPEND_WWW = False + +# list of regular expressions representing User-Agent strings that are not +# allowed to visit any page, CMS-wide. Use this for bad robots/crawlers. +DISALLOWED_USER_AGENTS = ( + re.compile(r'^NaverBot.*'), + re.compile(r'^EmailSiphon.*'), + re.compile(r'^SiteSucker.*'), + re.compile(r'^sohu-search') +) + +ABSOLUTE_URL_OVERRIDES = {} + +# list of allowed prefixes for the {% ssi %} tag +ALLOWED_INCLUDE_ROOTS = ('/home/html',) + +# if this is a admin settings module, this should be a list of +# settings modules for which this admin is an admin for +ADMIN_FOR = [] + +# 404s that may be ignored +IGNORABLE_404_STARTS = ('/cgi-bin/', '/_vti_bin', '/_vti_inf') +IGNORABLE_404_ENDS = ('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico', '.php') + +############## +# Middleware # +############## + +# List of middleware classes to use. Order is important; in the request phase, +# this middleware classes will be applied in the order given, and in the +# response phase the middleware will be applied in reverse order. +MIDDLEWARE_CLASSES = ( + "django.middleware.common.CommonMiddleware", + "django.middleware.doc.XViewMiddleware", +) + +######### +# CACHE # +######### + +# The cache backend to use. See the docstring in django.core.cache for the +# values this can be set to. +CACHE_BACKEND = 'simple://' + +#################### +# REGISTRATION # +#################### + +# E-mail addresses at these domains cannot sign up for accounts +BANNED_EMAIL_DOMAINS = [ + 'mailinator.com', 'dodgeit.com', 'spamgourmet.com', 'mytrashmail.com' +] +REGISTRATION_COOKIE_DOMAIN = None # set to a string like ".lawrence.com", or None for standard domain cookie + +# If this is set to True, users will be required to fill out their profile +# (defined by AUTH_PROFILE_MODULE) before they will be allowed to create +# an account. +REGISTRATION_REQUIRES_PROFILE = False + +#################### +# COMMENTS # +#################### + +COMMENTS_ALLOW_PROFANITIES = False + +# The group ID that designates which users are banned. +# Set to None if you're not using it. +COMMENTS_BANNED_USERS_GROUP = 19 + +# The group ID that designates which users can moderate comments. +# Set to None if you're not using it. +COMMENTS_MODERATORS_GROUP = 20 + +# The group ID that designates the users whose comments should be e-mailed to MANAGERS. +# Set to None if you're not using it. +COMMENTS_SKETCHY_USERS_GROUP = 22 + +# The system will e-mail MANAGERS the first COMMENTS_FIRST_FEW comments by each +# user. Set this to 0 if you want to disable it. +COMMENTS_FIRST_FEW = 10 + +BANNED_IPS = ( + # Dupont Stainmaster / GuessWho / a variety of other names (back when we had free comments) + '204.94.104.99', '66.142.59.23', '220.196.165.142', + # (Unknown) + '64.65.191.117', +# # Jimmy_Olsen / Clark_Kent / Bruce_Wayne +# # Unbanned on 2005-06-17, because other people want to register from this address. +# '12.106.111.10', + # hoof_hearted / hugh_Jass / Ferd_Burfel / fanny_farkel + '24.124.72.20', '170.135.241.46', + # Zac_McGraw + '198.74.20.74', '198.74.20.75', +) + +#################### +# BLOGS # +#################### + +# E-mail addresses to notify when a new blog entry is posted live +BLOGS_EMAILS_TO_NOTIFY = [] + +#################### +# PLACES # +#################### + +# A list of IDs -- *as integers, not strings* -- that are considered the "main" +# cities served by this installation. Probably just one. +MAIN_CITY_IDS = (1,) # Lawrence + +# A list of IDs -- *as integers, not strings* -- that are considered "local" by +# this installation. +LOCAL_CITY_IDS = (1, 3) # Lawrence and Kansas City, MO + +#################### +# THUMBNAILS # +#################### + +THUMB_ALLOWED_WIDTHS = (90, 120, 180, 240, 450) + +#################### +# VARIOUS ROOTS # +#################### + +# This is the new media root and URL! Use it, and only it! +MEDIA_ROOT = '/home/media/media.lawrence.com/' +MEDIA_URL = 'http://media.lawrence.com' diff --git a/django/conf/project_template/__init__.py b/django/conf/project_template/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/project_template/apps/__init__.py b/django/conf/project_template/apps/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/project_template/settings/__init__.py b/django/conf/project_template/settings/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/project_template/settings/main.py b/django/conf/project_template/settings/main.py new file mode 100644 index 0000000000..3db0e7961c --- /dev/null +++ b/django/conf/project_template/settings/main.py @@ -0,0 +1,31 @@ +# Django settings for {{ app_name }} project. + +DEBUG = False + +ADMINS = ( + # ('Your Name', 'your_email@domain.com'), +) + +MANAGERS = ADMINS + +LANGUAGE_CODE = 'en-us' + +DATABASE_ENGINE = 'postgresql' # Either 'postgresql' or 'mysql'. +DATABASE_NAME = '' +DATABASE_USER = '' +DATABASE_HOST = '' # Set to empty string for localhost. + +# Absolute path to the directory that holds media. +# Example: "/home/media/media.lawrence.com/" +MEDIA_ROOT = '' + +# URL that handles the media served from MEDIA_ROOT. +# Example: "http://media.lawrence.com" +MEDIA_URL = '' + +TEMPLATE_DIRS = ( + # Put strings here, like "/home/html/django_templates". +) + +INSTALLED_APPS = ( +) diff --git a/django/conf/settings.py b/django/conf/settings.py new file mode 100644 index 0000000000..dda46dba2f --- /dev/null +++ b/django/conf/settings.py @@ -0,0 +1,42 @@ +""" +Settings and configuration for Django. + +Values will be read from the module specified by the DJANGO_SETTINGS_MODULE environment +variable, and then from django.conf.global_settings; see the global settings file for +a list of all possible variables. +""" + +import os +import sys +from django.conf import global_settings + +# get a reference to this module (why isn't there a __module__ magic var?) +me = sys.modules[__name__] + +# update this dict from global settings (but only for ALL_CAPS settings) +for setting in dir(global_settings): + if setting == setting.upper(): + setattr(me, setting, getattr(global_settings, setting)) + +# try to load DJANGO_SETTINGS_MODULE +try: + mod = __import__(os.environ['DJANGO_SETTINGS_MODULE'], '', '', ['']) +except (KeyError, ImportError, ValueError): + pass +else: + for setting in dir(mod): + if setting == setting.upper(): + setattr(me, setting, getattr(mod, setting)) + +# save DJANGO_SETTINGS_MODULE in case anyone in the future cares +me.SETTINGS_MODULE = os.environ.get('DJANGO_SETTINGS_MODULE', '') + +# move the time zone info into os.environ +os.environ['TZ'] = me.TIME_ZONE + +# finally, clean up my namespace +for k in dir(me): + if not k.startswith('_') and k != 'me' and k != k.upper(): + delattr(me, k) +del me, k + diff --git a/django/conf/urls/__init__.py b/django/conf/urls/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/django/conf/urls/admin.py b/django/conf/urls/admin.py new file mode 100644 index 0000000000..92d5d1bc9e --- /dev/null +++ b/django/conf/urls/admin.py @@ -0,0 +1,56 @@ +from django.conf.urls.defaults import * +from django.conf.settings import INSTALLED_APPS + +urlpatterns = ( + ('^/?$', 'django.views.admin.main.index'), + ('^logout/$', 'django.views.admin.main.logout'), + ('^password_change/$', 'django.views.registration.passwords.password_change'), + ('^password_change/done/$', 'django.views.registration.passwords.password_change_done'), + ('^template_validator/$', 'django.views.admin.template.template_validator'), + + # Documentation + ('^doc/$', 'django.views.admin.doc.doc_index'), + ('^doc/bookmarklets/$', 'django.views.admin.doc.bookmarklets'), + ('^doc/tags/$', 'django.views.admin.doc.template_tag_index'), + ('^doc/filters/$', 'django.views.admin.doc.template_filter_index'), + ('^doc/views/$', 'django.views.admin.doc.view_index'), + ('^doc/views/jump/$', 'django.views.admin.doc.jump_to_view'), + ('^doc/views/(?P[^/]+)/$', 'django.views.admin.doc.view_detail'), + ('^doc/models/$', 'django.views.admin.doc.model_index'), + ('^doc/models/(?P[^/]+)/$', 'django.views.admin.doc.model_detail'), +) + +if 'ellington.events' in INSTALLED_APPS: + urlpatterns += ( + ("^events/usersubmittedevents/(?P\d+)/$", 'ellington.events.views.admin.user_submitted_event_change_stage'), + ("^events/usersubmittedevents/(?P\d+)/delete/$", 'ellington.events.views.admin.user_submitted_event_delete_stage'), + ) + +if 'ellington.news' in INSTALLED_APPS: + urlpatterns += ( + ("^stories/preview/$", 'ellington.news.views.admin.story_preview'), + ("^stories/js/inlinecontrols/$", 'ellington.news.views.admin.inlinecontrols_js'), + ("^stories/js/inlinecontrols/(?P