From 7202c7ccc86aa40eb3b29a568eacd8e9e510de9f Mon Sep 17 00:00:00 2001 From: Yuguang Zhang Date: Mon, 9 Mar 2026 03:30:37 +0000 Subject: [PATCH] Upgrade libraries and code for Django 4.2 LTS compatibility - Update Django from 1.4.16 to 4.2 LTS - Replace django-social-auth with social-auth-app-django (social_django) - Update INSTALLED_APPS: social_auth -> social_django - Update AUTHENTICATION_BACKENDS: social_auth.backends.* -> social_core.backends.* - Update settings to SOCIAL_AUTH__KEY/SECRET naming convention - Replace django-mediasync (abandoned) with django-storages for S3 support - Bump django-taggit to >= 5.0 - Remove django-chunks (unmaintained, incompatible with modern Django) - Modernize manage.py: replace execute_manager with execute_from_command_line - Modernize urls.py: replace patterns()/url() with list/re_path() - Modernize settings.default.py: - Replace TEMPLATE_LOADERS/TEMPLATE_CONTEXT_PROCESSORS/TEMPLATE_DIRS with TEMPLATES - Replace MIDDLEWARE_CLASSES with MIDDLEWARE - Update context processor paths (django.core -> django.template) - Remove deprecated ADMIN_MEDIA_PREFIX and TEMPLATE_DEBUG - Add DEFAULT_AUTO_FIELD - Fix Windows-style path separators - Fix files.py: handle missing sys.argv gracefully - Fix template {% url %} tag to use quoted names - Update setup-virtualenv.sh to use python3 -m venv Co-Authored-By: Oz --- files.py | 11 +-- manage.py | 34 +++++---- requirements.txt | 9 +-- settings.default.py | 154 +++++++++++++++++---------------------- setup-virtualenv.sh | 12 +-- templates/templates.html | 2 +- urls.py | 35 ++++----- 7 files changed, 120 insertions(+), 137 deletions(-) diff --git a/files.py b/files.py index 411895e..0b3dbad 100644 --- a/files.py +++ b/files.py @@ -1,10 +1,11 @@ import sys -command = sys.argv[1] -if command == 'syncmedia': - build_config = True -else: - build_config = False +try: + command = sys.argv[1] if len(sys.argv) > 1 else '' +except (IndexError, AttributeError): + command = '' + +build_config = (command == 'syncmedia') if not build_config: FILES = { diff --git a/manage.py b/manage.py index 3e4eedc..9863045 100644 --- a/manage.py +++ b/manage.py @@ -1,14 +1,22 @@ #!/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) +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pythonfiddle.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/requirements.txt b/requirements.txt index 9ae6ebf..132e9a8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ -django == 1.4.16 -django-mediasync >= 2.2.0 -django-social-auth >= 0.6.4 -django-taggit >= 0.9.3 -django-chunks >= 0.1 +django >= 4.2, < 5.0 +social-auth-app-django >= 5.0 +django-taggit >= 5.0 +django-storages >= 1.14 diff --git a/settings.default.py b/settings.default.py index 3283257..dea0476 100644 --- a/settings.default.py +++ b/settings.default.py @@ -1,27 +1,27 @@ # Django settings for pythonfiddle project. import os +from pathlib import Path + PROJECT_DIR = os.path.dirname(__file__) +BASE_DIR = Path(__file__).resolve().parent DEBUG = True -TEMPLATE_DEBUG = DEBUG -ADMINS = ( +ADMINS = [ # ('Your Name', 'your_email@example.com'), -) +] MANAGERS = ADMINS DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. - 'NAME': 'fiddle', # Or path to database file if using sqlite3. - 'USER': '', # Not used with sqlite3. - 'PASSWORD': '', # Not used with sqlite3. - 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. - 'PORT': '', # Set to empty string for default. Not used with sqlite3. + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'fiddle.sqlite3', } } +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + # Local time zone for this installation. Choices can be found here: # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name # although not all choices may be available on all operating systems. @@ -63,38 +63,33 @@ # Don't put anything in this directory yourself; store your static files # in apps' "static/" subdirectories and in STATICFILES_DIRS. # Example: "/home/media/media.lawrence.com/static/" -STATIC_ROOT = os.path.join(os.path.dirname(PROJECT_DIR), "fiddlesalad\\static") +STATIC_ROOT = os.path.join(os.path.dirname(PROJECT_DIR), "fiddlesalad", "static") -PYTHON_LIB_DIR = os.path.join(PROJECT_DIR, "static\\lib") +PYTHON_LIB_DIR = os.path.join(PROJECT_DIR, "static", "lib") # URL prefix for static files. # Example: "http://media.lawrence.com/static/" STATIC_URL = 'http://127.0.0.1:8000/static/' -# URL prefix for admin static files -- CSS, JavaScript and images. -# Make sure to use a trailing slash. -# Examples: "http://foo.com/static/admin/", "/static/admin/". -ADMIN_MEDIA_PREFIX = '/static/admin/' - AWS_ACCESS_KEY_ID = 's3_key' AWS_SECRET_ACCESS_KEY = 's3_secret' AWS_STORAGE_BUCKET_NAME = 'bucket_name' -build_config = False - -from files import * -# Media files -MEDIASYNC = { - 'BACKEND': 'mediasync.backends.s3', - 'AWS_KEY': AWS_ACCESS_KEY_ID, - 'AWS_SECRET': AWS_SECRET_ACCESS_KEY, - 'AWS_BUCKET': AWS_STORAGE_BUCKET_NAME, - 'JOINED': MEDIASYNC_JOINED, +# django-storages S3 configuration (replaces django-mediasync) +STORAGES = { + 'staticfiles': { + 'BACKEND': 'storages.backends.s3boto3.S3Boto3Storage', + }, } +AWS_S3_ACCESS_KEY_ID = AWS_ACCESS_KEY_ID +AWS_S3_SECRET_ACCESS_KEY = AWS_SECRET_ACCESS_KEY +AWS_STORAGE_BUCKET_NAME = AWS_STORAGE_BUCKET_NAME + +build_config = False -MEDIASYNC['SERVE_REMOTE'] = False +from pythonfiddle.files import * # Additional locations of static files STATICFILES_DIRS = ( @@ -108,33 +103,37 @@ STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', -# 'django.contrib.staticfiles.finders.DefaultStorageFinder', ) # Make this unique, and don't share it with anybody. SECRET_KEY = 'o#&0=io58r!=dhaf(gx@a5$n#2zy!b$k=yhu&^@uq^7=$v%&k(' -# 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', -# 'django.template.loaders.eggs.Loader', -) - -TEMPLATE_CONTEXT_PROCESSORS = ( - 'django.contrib.auth.context_processors.auth', - 'django.core.context_processors.debug', - 'django.core.context_processors.i18n', - 'django.core.context_processors.media', - 'django.core.context_processors.static', - 'django.contrib.messages.context_processors.messages', - 'django.core.context_processors.request', - 'cloud_ide.context_processors.debug', - 'cloud_ide.context_processors.media', - 'pythonfiddle.context_processors.site', -) +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ + os.path.join(os.path.dirname(PROJECT_DIR), 'templates'), + os.path.join(PROJECT_DIR, 'templates'), + ], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.template.context_processors.i18n', + 'django.template.context_processors.media', + 'django.template.context_processors.static', + 'django.contrib.messages.context_processors.messages', + 'cloud_ide.context_processors.debug', + 'cloud_ide.context_processors.media', + 'pythonfiddle.context_processors.site', + ], + }, + }, +] -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = [ 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware', @@ -142,21 +141,16 @@ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.contrib.redirects.middleware.RedirectFallbackMiddleware', - 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware' -) + 'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware', +] ROOT_URLCONF = 'pythonfiddle.urls' -TEMPLATE_DIRS = ( - os.path.join(os.path.dirname(PROJECT_DIR), "templates"), - os.path.join(PROJECT_DIR, "templates"), - ) - LOCALE_PATHS = ( os.path.join(PROJECT_DIR, "locale"), ) -INSTALLED_APPS = ( +INSTALLED_APPS = [ 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', @@ -167,44 +161,32 @@ 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.redirects', - 'mediasync', + 'storages', 'taggit', - 'social_auth', - 'chunks', + 'social_django', 'cloud_ide.fiddle', - # Uncomment the next line to enable the admin: - # 'django.contrib.admin', - # Uncomment the next line to enable admin documentation: - # 'django.contrib.admindocs', -) +] -AUTHENTICATION_BACKENDS = ( - 'social_auth.backends.twitter.TwitterBackend', - 'social_auth.backends.facebook.FacebookBackend', - 'social_auth.backends.google.GoogleOAuthBackend', +AUTHENTICATION_BACKENDS = [ + 'social_core.backends.twitter.TwitterOAuth', + 'social_core.backends.facebook.FacebookOAuth2', + 'social_core.backends.google.GoogleOAuth2', 'django.contrib.auth.backends.ModelBackend', -) +] LOGIN_URL = '/login/' LOGIN_REDIRECT_URL = '/done/' -TWITTER_CONSUMER_KEY = '65tXXWpGJ0PfsZzN1xR7Q' -TWITTER_CONSUMER_SECRET = 'KZa2FPOjIByvdFqcHGTQNi01VouoTiqeAaZ8yelTh0' -FACEBOOK_APP_ID = '244638052233650' -FACEBOOK_API_SECRET = '66c1d60fe6f777dc52c2c3eef5752fbf' -LINKEDIN_CONSUMER_KEY = '' -LINKEDIN_CONSUMER_SECRET = '' -ORKUT_CONSUMER_KEY = '' -ORKUT_CONSUMER_SECRET = '' -GOOGLE_OAUTH2_CLIENT_KEY = '823652973862.apps.googleusercontent.com' -GOOGLE_OAUTH2_CLIENT_SECRET = 'yQ4l2KebfymlugAnTgS6l2ID' -SOCIAL_AUTH_CREATE_USERS = True -SOCIAL_AUTH_FORCE_RANDOM_USERNAME = False -SOCIAL_AUTH_DEFAULT_USERNAME = 'socialauth_user' -SOCIAL_AUTH_COMPLETE_URL_NAME = 'socialauth_complete' -LOGIN_ERROR_URL = '/login/error/' -#SOCIAL_AUTH_USER_MODEL = 'app.CustomUser' -SOCIAL_AUTH_ERROR_KEY = 'socialauth_error' +# python-social-auth settings (replaces django-social-auth) +SOCIAL_AUTH_TWITTER_KEY = '65tXXWpGJ0PfsZzN1xR7Q' +SOCIAL_AUTH_TWITTER_SECRET = 'KZa2FPOjIByvdFqcHGTQNi01VouoTiqeAaZ8yelTh0' +SOCIAL_AUTH_FACEBOOK_KEY = '244638052233650' +SOCIAL_AUTH_FACEBOOK_SECRET = '66c1d60fe6f777dc52c2c3eef5752fbf' +SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '823652973862.apps.googleusercontent.com' +SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = 'yQ4l2KebfymlugAnTgS6l2ID' +SOCIAL_AUTH_CREATE_USERS = True +SOCIAL_AUTH_DEFAULT_USERNAME = 'socialauth_user' +LOGIN_ERROR_URL = '/login/error/' # A sample logging configuration. The only tangible logging # performed by this configuration is to send an email to diff --git a/setup-virtualenv.sh b/setup-virtualenv.sh index 540de99..4304500 100755 --- a/setup-virtualenv.sh +++ b/setup-virtualenv.sh @@ -1,7 +1,6 @@ #!/usr/bin/env bash -VERSION=1.9.1 -VIRTUALENV="virtualenv-${VERSION}.tar.gz" +# Using python3 built-in venv module (no external virtualenv needed) read -r -d '' HELP < /dev/null - python2 virtualenv.py --no-site-packages ../dev-python - popd > /dev/null - - rm -r "${VIRTUALENV%%.tar.gz}" - rm "${VIRTUALENV}" + python3 -m venv dev-python fi diff --git a/templates/templates.html b/templates/templates.html index a77b28f..08653f9 100644 --- a/templates/templates.html +++ b/templates/templates.html @@ -46,7 +46,7 @@

{% trans "Pages" %}

{% for page in flatpages %}

{{ page.title }}

{% endfor %} -

{% trans "All Fiddles" %}

+

{% trans "All Fiddles" %}

Python Idioms

The Python Tutorial

diff --git a/urls.py b/urls.py index 2b19cb9..974c6a1 100644 --- a/urls.py +++ b/urls.py @@ -1,23 +1,24 @@ -from django.conf.urls.defaults import patterns, include, url +from django.urls import re_path, include +from django.views.static import serve + from pythonfiddle.settings import DEBUG, PYTHON_LIB_DIR from cloud_ide.shared.urls import urlpatterns as shared_urls +from cloud_ide.fiddle import views as fiddle_views -urlpatterns = shared_urls + patterns('cloud_ide.fiddle.views', - url(r'^$', 'create', name='create_snippet'), - url(r'^save/$', 'save', name='save_snippet'), - url(r'^check_title/', 'check_title'), - url(r'^tag_hint/$', 'tag_hint'), - url(r'^(?P[-\w]+)/$', 'open', name='open_snippet'), - url(r'^(?P[-\w]+)/embedded/$', 'open', {'embedded': True}), -) +urlpatterns = shared_urls + [ + re_path(r'^$', fiddle_views.create, name='create_snippet'), + re_path(r'^save/$', fiddle_views.save, name='save_snippet'), + re_path(r'^check_title/', fiddle_views.check_title), + re_path(r'^tag_hint/$', fiddle_views.tag_hint), + re_path(r'^(?P[-\w]+)/$', fiddle_views.open, name='open_snippet'), + re_path(r'^(?P[-\w]+)/embedded/$', fiddle_views.open, {'embedded': True}), +] -urlpatterns += patterns('', - url(r'^i18n/', include('django.conf.urls.i18n')), -) +urlpatterns += [ + re_path(r'^i18n/', include('django.conf.urls.i18n')), +] if DEBUG: - urlpatterns += patterns('', ( - r'^lib/(?P.*)$', - 'django.views.static.serve', - {'document_root': PYTHON_LIB_DIR} - )) \ No newline at end of file + urlpatterns += [ + re_path(r'^lib/(?P.*)$', serve, {'document_root': PYTHON_LIB_DIR}), + ]