Skip to content

Commit

Permalink
Fixed django#5522 -- Moved make-messages, compile-messages and daily-…
Browse files Browse the repository at this point in the history
…cleanup into django-admin.py.

They are now called  "makemessages", "compilemessages" and "cleanup". This is
backwards incompatible for make-messages.py and compile-messages.py, although
the old executables still exist for now and print an error pointing the caller
to the right command to call.

This reduces the number of binaries and man pages Django needs to install.

Patch from Janis Leidel.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@7844 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
malcolmt committed Jul 6, 2008
1 parent bff0759 commit 3cfa3cb
Show file tree
Hide file tree
Showing 16 changed files with 418 additions and 381 deletions.
69 changes: 8 additions & 61 deletions django/bin/compile-messages.py
Original file line number Diff line number Diff line change
@@ -1,64 +1,11 @@
#!/usr/bin/env python

import optparse
import os
import sys

try:
set
except NameError:
from sets import Set as set # For Python 2.3


def compile_messages(locale=None):
basedirs = (os.path.join('conf', 'locale'), 'locale')
if os.environ.get('DJANGO_SETTINGS_MODULE'):
from django.conf import settings
basedirs += settings.LOCALE_PATHS

# Gather existing directories.
basedirs = set(map(os.path.abspath, filter(os.path.isdir, basedirs)))

if not basedirs:
print "This script should be run from the Django SVN tree or your project or app tree, or with the settings module specified."
sys.exit(1)

for basedir in basedirs:
if locale:
basedir = os.path.join(basedir, locale, 'LC_MESSAGES')
compile_messages_in_dir(basedir)

def compile_messages_in_dir(basedir):
for dirpath, dirnames, filenames in os.walk(basedir):
for f in filenames:
if f.endswith('.po'):
sys.stderr.write('processing file %s in %s\n' % (f, dirpath))
pf = os.path.splitext(os.path.join(dirpath, f))[0]
# Store the names of the .mo and .po files in an environment
# variable, rather than doing a string replacement into the
# command, so that we can take advantage of shell quoting, to
# quote any malicious characters/escaping.
# See http://cyberelk.net/tim/articles/cmdline/ar01s02.html
os.environ['djangocompilemo'] = pf + '.mo'
os.environ['djangocompilepo'] = pf + '.po'
if sys.platform == 'win32': # Different shell-variable syntax
cmd = 'msgfmt --check-format -o "%djangocompilemo%" "%djangocompilepo%"'
else:
cmd = 'msgfmt --check-format -o "$djangocompilemo" "$djangocompilepo"'
os.system(cmd)

def main():
parser = optparse.OptionParser()
parser.add_option('-l', '--locale', dest='locale',
help="The locale to process. Default is to process all.")
parser.add_option('--settings',
help='Python path to settings module, e.g. "myproject.settings". If provided, all LOCALE_PATHS will be processed. If this isn\'t provided, the DJANGO_SETTINGS_MODULE environment variable will be checked as well.')
options, args = parser.parse_args()
if len(args):
parser.error("This program takes no arguments")
if options.settings:
os.environ['DJANGO_SETTINGS_MODULE'] = options.settings
compile_messages(options.locale)

if __name__ == "__main__":
main()
import sys
name = sys.argv[0]
args = ' '.join(sys.argv[1:])
print >> sys.stderr, "%s has been moved into django-admin.py" % name
print >> sys.stderr, 'Please run "django-admin.py compilemessages %s" instead.'% args
print >> sys.stderr
sys.exit(1)

11 changes: 2 additions & 9 deletions django/bin/daily_cleanup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,7 @@
sessions at the moment).
"""

import datetime
from django.db import transaction
from django.contrib.sessions.models import Session

def clean_up():
"""Clean up expired sessions."""
Session.objects.filter(expire_date__lt=datetime.datetime.now()).delete()
transaction.commit_unless_managed()
from django.core import management

if __name__ == "__main__":
clean_up()
management.call_command('cleanup')
164 changes: 8 additions & 156 deletions django/bin/make-messages.py
Original file line number Diff line number Diff line change
@@ -1,159 +1,11 @@
#!/usr/bin/env python

# Need to ensure that the i18n framework is enabled
from django.conf import settings
settings.configure(USE_I18N = True)

from django.utils.translation import templatize
import re
import os
import sys
import getopt
from itertools import dropwhile

pythonize_re = re.compile(r'\n\s*//')

def make_messages():
localedir = None

if os.path.isdir(os.path.join('conf', 'locale')):
localedir = os.path.abspath(os.path.join('conf', 'locale'))
elif os.path.isdir('locale'):
localedir = os.path.abspath('locale')
else:
print "This script should be run from the django svn tree or your project or app tree."
print "If you did indeed run it from the svn checkout or your project or application,"
print "maybe you are just missing the conf/locale (in the django tree) or locale (for project"
print "and application) directory?"
print "make-messages.py doesn't create it automatically, you have to create it by hand if"
print "you want to enable i18n for your project or application."
sys.exit(1)

(opts, args) = getopt.getopt(sys.argv[1:], 'l:d:va')

lang = None
domain = 'django'
verbose = False
all = False

for o, v in opts:
if o == '-l':
lang = v
elif o == '-d':
domain = v
elif o == '-v':
verbose = True
elif o == '-a':
all = True

if domain not in ('django', 'djangojs'):
print "currently make-messages.py only supports domains 'django' and 'djangojs'"
sys.exit(1)
if (lang is None and not all) or domain is None:
print "usage: make-messages.py -l <language>"
print " or: make-messages.py -a"
sys.exit(1)

languages = []

if lang is not None:
languages.append(lang)
elif all:
languages = [el for el in os.listdir(localedir) if not el.startswith('.')]

for lang in languages:

print "processing language", lang
basedir = os.path.join(localedir, lang, 'LC_MESSAGES')
if not os.path.isdir(basedir):
os.makedirs(basedir)

pofile = os.path.join(basedir, '%s.po' % domain)
potfile = os.path.join(basedir, '%s.pot' % domain)

if os.path.exists(potfile):
os.unlink(potfile)

all_files = []
for (dirpath, dirnames, filenames) in os.walk("."):
all_files.extend([(dirpath, f) for f in filenames])
all_files.sort()
for dirpath, file in all_files:
if domain == 'djangojs' and file.endswith('.js'):
if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
src = open(os.path.join(dirpath, file), "rb").read()
src = pythonize_re.sub('\n#', src)
open(os.path.join(dirpath, '%s.py' % file), "wb").write(src)
thefile = '%s.py' % file
cmd = 'xgettext -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (domain, os.path.join(dirpath, thefile))
(stdin, stdout, stderr) = os.popen3(cmd, 't')
msgs = stdout.read()
errors = stderr.read()
if errors:
print "errors happened while running xgettext on %s" % file
print errors
sys.exit(8)
old = '#: '+os.path.join(dirpath, thefile)[2:]
new = '#: '+os.path.join(dirpath, file)[2:]
msgs = msgs.replace(old, new)
if os.path.exists(potfile):
# Strip the header
msgs = '\n'.join(dropwhile(len, msgs.split('\n')))
else:
msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8')
if msgs:
open(potfile, 'ab').write(msgs)
os.unlink(os.path.join(dirpath, thefile))
elif domain == 'django' and (file.endswith('.py') or file.endswith('.html')):
thefile = file
if file.endswith('.html'):
src = open(os.path.join(dirpath, file), "rb").read()
thefile = '%s.py' % file
open(os.path.join(dirpath, thefile), "wb").write(templatize(src))
if verbose:
sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
cmd = 'xgettext -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy:1,2 --keyword=ugettext_noop --keyword=ugettext_lazy --keyword=ungettext_lazy:1,2 --from-code UTF-8 -o - "%s"' % (
domain, os.path.join(dirpath, thefile))
(stdin, stdout, stderr) = os.popen3(cmd, 't')
msgs = stdout.read()
errors = stderr.read()
if errors:
print "errors happened while running xgettext on %s" % file
print errors
sys.exit(8)
if thefile != file:
old = '#: '+os.path.join(dirpath, thefile)[2:]
new = '#: '+os.path.join(dirpath, file)[2:]
msgs = msgs.replace(old, new)
if os.path.exists(potfile):
# Strip the header
msgs = '\n'.join(dropwhile(len, msgs.split('\n')))
else:
msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8')
if msgs:
open(potfile, 'ab').write(msgs)
if thefile != file:
os.unlink(os.path.join(dirpath, thefile))

if os.path.exists(potfile):
(stdin, stdout, stderr) = os.popen3('msguniq --to-code=utf-8 "%s"' % potfile, 'b')
msgs = stdout.read()
errors = stderr.read()
if errors:
print "errors happened while running msguniq"
print errors
sys.exit(8)
open(potfile, 'w').write(msgs)
if os.path.exists(pofile):
(stdin, stdout, stderr) = os.popen3('msgmerge -q "%s" "%s"' % (pofile, potfile), 'b')
msgs = stdout.read()
errors = stderr.read()
if errors:
print "errors happened while running msgmerge"
print errors
sys.exit(8)
open(pofile, 'wb').write(msgs)
os.unlink(potfile)

if __name__ == "__main__":
make_messages()
import sys
name = sys.argv[0]
args = ' '.join(sys.argv[1:])
print >> sys.stderr, "%s has been moved into django-admin.py" % name
print >> sys.stderr, 'Please run "django-admin.py makemessages %s" instead.'% args
print >> sys.stderr
sys.exit(1)

5 changes: 5 additions & 0 deletions django/core/management/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
from django.core.exceptions import ImproperlyConfigured
from django.core.management.color import color_style

try:
set
except NameError:
from sets import Set as set # For Python 2.3

class CommandError(Exception):
pass

Expand Down
11 changes: 11 additions & 0 deletions django/core/management/commands/cleanup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import datetime
from django.core.management.base import NoArgsCommand

class Command(NoArgsCommand):
help = "Can be run as a cronjob or directly to clean out old data from the database (only expired sessions at the moment)."

def handle_noargs(self, **options):
from django.db import transaction
from django.contrib.sessions.models import Session
Session.objects.filter(expire_date__lt=datetime.datetime.now()).delete()
transaction.commit_unless_managed()
58 changes: 58 additions & 0 deletions django/core/management/commands/compilemessages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import os
import sys
from optparse import make_option
from django.core.management.base import BaseCommand
from django.core.management.color import no_style

try:
set
except NameError:
from sets import Set as set # For Python 2.3

def compile_messages(locale=None):
basedirs = (os.path.join('conf', 'locale'), 'locale')
if os.environ.get('DJANGO_SETTINGS_MODULE'):
from django.conf import settings
basedirs += settings.LOCALE_PATHS

# Gather existing directories.
basedirs = set(map(os.path.abspath, filter(os.path.isdir, basedirs)))

if not basedirs:
raise CommandError("This script should be run from the Django SVN tree or your project or app tree, or with the settings module specified.")

for basedir in basedirs:
if locale:
basedir = os.path.join(basedir, locale, 'LC_MESSAGES')
for dirpath, dirnames, filenames in os.walk(basedir):
for f in filenames:
if f.endswith('.po'):
sys.stderr.write('processing file %s in %s\n' % (f, dirpath))
pf = os.path.splitext(os.path.join(dirpath, f))[0]
# Store the names of the .mo and .po files in an environment
# variable, rather than doing a string replacement into the
# command, so that we can take advantage of shell quoting, to
# quote any malicious characters/escaping.
# See http://cyberelk.net/tim/articles/cmdline/ar01s02.html
os.environ['djangocompilemo'] = pf + '.mo'
os.environ['djangocompilepo'] = pf + '.po'
if sys.platform == 'win32': # Different shell-variable syntax
cmd = 'msgfmt --check-format -o "%djangocompilemo%" "%djangocompilepo%"'
else:
cmd = 'msgfmt --check-format -o "$djangocompilemo" "$djangocompilepo"'
os.system(cmd)


class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--locale', '-l', dest='locale',
help='The locale to process. Default is to process all.'),
)
help = 'Compiles .po files to .mo files for use with builtin gettext support.'

requires_model_validation = False
can_import_settings = False

def handle(self, **options):
locale = options.get('locale')
compile_messages(locale)
Loading

0 comments on commit 3cfa3cb

Please sign in to comment.