Ticket #5465: django-package.diff

File django-package.diff, 31.5 KB (added by Jannis Leidel, 17 years ago)
  • django/core/management/commands/startapp.py

     
     1import os
     2from optparse import make_option
    13from django.core.management.base import copy_helper, CommandError, LabelCommand
    2 import os
    34
    45class Command(LabelCommand):
     6    option_list = LabelCommand.option_list + (
     7        make_option('--noskeleton', action='store_false', dest='use_skeleton', default=True,
     8            help='Tells Django to NOT create the application with skeleton data.'),
     9    )
    510    help = "Creates a Django app directory structure for the given app name in the current directory."
    611    args = "[appname]"
    712    label = 'application name'
     
    1217    can_import_settings = False
    1318
    1419    def handle_label(self, app_name, directory=None, **options):
     20        use_skeleton = options.get('use_skeleton', True)
    1521        if directory is None:
    1622            directory = os.getcwd()
    1723        # Determine the project_name a bit naively -- by looking at the name of
     
    1925        project_dir = os.path.normpath(os.path.join(directory, '..'))
    2026        parent_dir = os.path.basename(project_dir)
    2127        project_name = os.path.basename(directory)
    22         if app_name == project_name:
    23             raise CommandError("You cannot create an app with the same name (%r) as your project." % app_name)
     28        if use_skeleton:
     29            directory = os.path.join(directory, app_name)
     30            try:
     31                os.mkdir(directory)
     32            except OSError, e:
     33                raise CommandError(e)
     34        else:
     35            if app_name == project_name:
     36                raise CommandError("You cannot create an app with the same name (%r) as your project." % app_name)
    2437        copy_helper(self.style, 'app', app_name, directory, parent_dir)
     38        if use_skeleton:
     39            from django.utils import package
     40            package.standalone_app(directory, app_name)
    2541
    2642class ProjectCommand(Command):
    2743    help = "Creates a Django app directory structure for the given app name in this project's directory."
  • django/core/management/commands/editapp.py

     
     1from django.core.management.base import LabelCommand, CommandError
     2import os
     3
     4class Command(LabelCommand):
     5    help = "Edits releae metadata of the Django app in the current directory."
     6    args = "[appname]"
     7    label = 'application name'
     8   
     9    requires_model_validation = False
     10    # Can't import settings during this command, because they haven't
     11    # necessarily been created.
     12    can_import_settings = False
     13   
     14    def handle_label(self, app_name, directory=None, **options):
     15        if directory is None:
     16            directory = os.getcwd()
     17        release_dir = os.path.join(directory, app_name)
     18        release_file = os.path.join(directory, "release.py")
     19       
     20        if os.path.isdir(release_dir) and os.path.isfile(release_file):
     21            from django.utils import package
     22            release = package.Release(directory)
     23            if release.loaded:
     24                package.standalone_app(directory)
     25            else:
     26                raise CommandError("The release.py file does not contain any data.")
     27        elif not os.path.isdir(release_dir) and \
     28                os.path.isfile(release_file):
     29            raise CommandError("There is a release.py file but the given appname doesn't match.")
     30        else:
     31            raise CommandError("There is no release.py file in the current directory.")
  • django/views/debug.py

     
    705705  <p>Of course, you haven't actually done any work yet. Here's what to do next:</p>
    706706  <ul>
    707707    <li>If you plan to use a database, edit the <code>DATABASE_*</code> settings in <code>{{ project_name }}/settings.py</code>.</li>
    708     <li>Start your first app by running <code>python {{ project_name }}/manage.py startapp [appname]</code>.</li>
     708    <li>Start your first app by running <code>python {{ project_name }}/manage.py --noskeleton startapp [appname]</code>.</li>
    709709  </ul>
    710710</div>
    711711
  • django/utils/package/validators.py

     
     1"Validators used for package management"
     2import os, sys, re
     3from pkg_resources import safe_version, safe_name
     4from django.core import validators
     5
     6INVALID_APP_NAMES = ('django', 'site', 'test', 'tests', 'release', 'doc', 'docs')
     7find_keywords_re = re.compile(r'[-\w\.]+')
     8
     9def isvalidname(value):
     10    if value.lower() in INVALID_APP_NAMES:
     11        sys.stderr.write("Error: That app name is invalid. Please use another name.\n")
     12        return False
     13    return True
     14
     15def isvalidversion(value):
     16    if not value or value.startswith("-"):
     17        sys.stderr.write("Error: That version number is invalid. Use only letters and digits.\n")
     18        return False
     19    return True
     20
     21def isalnum(value):
     22    if not value.isalnum():
     23        sys.stderr.write("Error: That input is invalid. Use only letters, digits and underscores.\n")
     24        return False
     25    return True
     26
     27def isgiven(value):
     28    if not value:
     29        sys.stderr.write("Error: This field is required.\n")
     30        return False
     31    return True
     32
     33def iskeywordlist(value):
     34    if not find_keywords_re.search(value):
     35        sys.stderr.write("Error: This keyword list is invalid.\n")
     36        return False
     37    return True
     38
     39def isemailadress(value):
     40    if not validators.email_re.search(value):
     41        sys.stderr.write("Error: That e-mail address is invalid.\n")
     42        return False
     43    return True
     44
     45def isyesorno(value):
     46    if not value.lower() in ('yes', 'no'):
     47        sys.stderr.write("Error: Please enter yes or no.\n")
     48        return False
     49    return True
  • django/utils/package/ez_setup.py

     
     1#!python
     2"""Bootstrap setuptools installation
     3
     4If you want to use setuptools in your package's setup.py, just include this
     5file in the same directory with it, and add this to the top of your setup.py::
     6
     7    from ez_setup import use_setuptools
     8    use_setuptools()
     9
     10If you want to require a specific version of setuptools, set a download
     11mirror, or use an alternate download directory, you can do so by supplying
     12the appropriate options to ``use_setuptools()``.
     13
     14This file can also be run as a script to install or upgrade setuptools.
     15"""
     16import sys
     17DEFAULT_VERSION = "0.6c6"
     18DEFAULT_URL     = "http://cheeseshop.python.org/packages/%s/s/setuptools/" % sys.version[:3]
     19
     20md5_data = {
     21    'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
     22    'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
     23    'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',
     24    'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',
     25    'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',
     26    'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',
     27    'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',
     28    'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',
     29    'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',
     30    'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',
     31    'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',
     32    'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',
     33    'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',
     34    'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',
     35    'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',
     36    'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',
     37    'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',
     38    'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',
     39    'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',
     40    'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',
     41    'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',
     42    'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',
     43    'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',
     44    'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',
     45}
     46
     47import sys, os
     48
     49def _validate_md5(egg_name, data):
     50    if egg_name in md5_data:
     51        from md5 import md5
     52        digest = md5(data).hexdigest()
     53        if digest != md5_data[egg_name]:
     54            print >>sys.stderr, (
     55                "md5 validation of %s failed!  (Possible download problem?)"
     56                % egg_name
     57            )
     58            sys.exit(2)
     59    return data
     60
     61
     62def use_setuptools(
     63    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
     64    download_delay=15
     65):
     66    """Automatically find/download setuptools and make it available on sys.path
     67
     68    `version` should be a valid setuptools version number that is available
     69    as an egg for download under the `download_base` URL (which should end with
     70    a '/').  `to_dir` is the directory where setuptools will be downloaded, if
     71    it is not already available.  If `download_delay` is specified, it should
     72    be the number of seconds that will be paused before initiating a download,
     73    should one be required.  If an older version of setuptools is installed,
     74    this routine will print a message to ``sys.stderr`` and raise SystemExit in
     75    an attempt to abort the calling script.
     76    """
     77    try:
     78        import setuptools
     79        if setuptools.__version__ == '0.0.1':
     80            print >>sys.stderr, (
     81            "You have an obsolete version of setuptools installed.  Please\n"
     82            "remove it from your system entirely before rerunning this script."
     83            )
     84            sys.exit(2)
     85    except ImportError:
     86        egg = download_setuptools(version, download_base, to_dir, download_delay)
     87        sys.path.insert(0, egg)
     88        import setuptools; setuptools.bootstrap_install_from = egg
     89
     90    import pkg_resources
     91    try:
     92        pkg_resources.require("setuptools>="+version)
     93
     94    except pkg_resources.VersionConflict, e:
     95        # XXX could we install in a subprocess here?
     96        print >>sys.stderr, (
     97            "The required version of setuptools (>=%s) is not available, and\n"
     98            "can't be installed while this script is running. Please install\n"
     99            " a more recent version first.\n\n(Currently using %r)"
     100        ) % (version, e.args[0])
     101        sys.exit(2)
     102
     103def download_setuptools(
     104    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
     105    delay = 15
     106):
     107    """Download setuptools from a specified location and return its filename
     108
     109    `version` should be a valid setuptools version number that is available
     110    as an egg for download under the `download_base` URL (which should end
     111    with a '/'). `to_dir` is the directory where the egg will be downloaded.
     112    `delay` is the number of seconds to pause before an actual download attempt.
     113    """
     114    import urllib2, shutil
     115    egg_name = "setuptools-%s-py%s.egg" % (version,sys.version[:3])
     116    url = download_base + egg_name
     117    saveto = os.path.join(to_dir, egg_name)
     118    src = dst = None
     119    if not os.path.exists(saveto):  # Avoid repeated downloads
     120        try:
     121            from distutils import log
     122            if delay:
     123                log.warn("""
     124---------------------------------------------------------------------------
     125This script requires setuptools version %s to run (even to display
     126help).  I will attempt to download it for you (from
     127%s), but
     128you may need to enable firewall access for this script first.
     129I will start the download in %d seconds.
     130
     131(Note: if this machine does not have network access, please obtain the file
     132
     133   %s
     134
     135and place it in this directory before rerunning this script.)
     136---------------------------------------------------------------------------""",
     137                    version, download_base, delay, url
     138                ); from time import sleep; sleep(delay)
     139            log.warn("Downloading %s", url)
     140            src = urllib2.urlopen(url)
     141            # Read/write all in one block, so we don't create a corrupt file
     142            # if the download is interrupted.
     143            data = _validate_md5(egg_name, src.read())
     144            dst = open(saveto,"wb"); dst.write(data)
     145        finally:
     146            if src: src.close()
     147            if dst: dst.close()
     148    return os.path.realpath(saveto)
     149
     150def main(argv, version=DEFAULT_VERSION):
     151    """Install or upgrade setuptools and EasyInstall"""
     152
     153    try:
     154        import setuptools
     155    except ImportError:
     156        egg = None
     157        try:
     158            egg = download_setuptools(version, delay=0)
     159            sys.path.insert(0,egg)
     160            from setuptools.command.easy_install import main
     161            return main(list(argv)+[egg])   # we're done here
     162        finally:
     163            if egg and os.path.exists(egg):
     164                os.unlink(egg)
     165    else:
     166        if setuptools.__version__ == '0.0.1':
     167            # tell the user to uninstall obsolete version
     168            use_setuptools(version)
     169
     170    req = "setuptools>="+version
     171    import pkg_resources
     172    try:
     173        pkg_resources.require(req)
     174    except pkg_resources.VersionConflict:
     175        try:
     176            from setuptools.command.easy_install import main
     177        except ImportError:
     178            from easy_install import main
     179        main(list(argv)+[download_setuptools(delay=0)])
     180        sys.exit(0) # try to force an exit
     181    else:
     182        if argv:
     183            from setuptools.command.easy_install import main
     184            main(argv)
     185        else:
     186            print "Setuptools version",version,"or greater has been installed."
     187            print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
     188
     189
     190
     191def update_md5(filenames):
     192    """Update our built-in md5 registry"""
     193
     194    import re
     195    from md5 import md5
     196
     197    for name in filenames:
     198        base = os.path.basename(name)
     199        f = open(name,'rb')
     200        md5_data[base] = md5(f.read()).hexdigest()
     201        f.close()
     202
     203    data = ["    %r: %r,\n" % it for it in md5_data.items()]
     204    data.sort()
     205    repl = "".join(data)
     206
     207    import inspect
     208    srcfile = inspect.getsourcefile(sys.modules[__name__])
     209    f = open(srcfile, 'rb'); src = f.read(); f.close()
     210
     211    match = re.search("\nmd5_data = {\n([^}]+)}", src)
     212    if not match:
     213        print >>sys.stderr, "Internal error!"
     214        sys.exit(2)
     215
     216    src = src[:match.start(1)] + repl + src[match.end(1):]
     217    f = open(srcfile,'w')
     218    f.write(src)
     219    f.close()
     220
     221
     222if __name__=='__main__':
     223    if len(sys.argv)>2 and sys.argv[1]=='--md5update':
     224        update_md5(sys.argv[2:])
     225    else:
     226        main(sys.argv[1:])
     227
     228
     229
     230
  • django/utils/package/__init__.py

     
     1from ez_setup import use_setuptools
     2use_setuptools()
     3
     4import os, sys, urlparse, shutil
     5from setuptools import setup as original_setup
     6from pkg_resources import safe_version, safe_name
     7
     8from django.core.management.base import CommandError
     9from django.utils.package.prompts import *
     10
     11def setup(**args):
     12    """
     13    Hacky wrapper to make sure that the default PyPI keyword is included when
     14    the setup.py of an app is used
     15    """
     16    keywords = args.get('keyword', PYPI_KEYWORD)
     17    if PYPI_KEYWORD not in keywords:
     18        args['keyword'] = "%s %s" % (PYPI_KEYWORD, args['keyword'])
     19    original_setup(args)
     20
     21def generate_default_files(template_dir):
     22    """
     23    Generates a list of filepaths and appendant content.
     24    """
     25    for d, subdirs, files in os.walk(template_dir):
     26        for f in files:
     27            parent = os.path.basename(d)
     28            if f.startswith('.') or f.endswith('.pyc') or parent.startswith('.'):
     29                continue
     30            filepath = os.path.join(d, f)
     31            filecontent = open(filepath, 'r').read()
     32            yield (os.path.basename(filepath), filecontent)
     33
     34# could also be combined with skeleton files in django.conf (?)s
     35TEMPLATE_DIR =  os.path.join(os.path.abspath(os.path.dirname(__file__)), "templates")
     36DEFAULT_FILES = generate_default_files(TEMPLATE_DIR)
     37DEFAULT_DIRECTORIES = ('docs', 'tests', '%(NAME)s/templates/%(NAME)s')
     38APP_REPOSITORY_URL = "http://www.djangoproject.com/apps/"
     39
     40class Release(dict):
     41    """
     42    Wrapper to handle release metadata from release.py and make it available
     43    as items and attributes of a dict object. Setting attributes will actually
     44    set the dict items.
     45    """
     46    def __init__(self, directory, internal=None):
     47        self.directory = directory
     48        self.renamed_name = False
     49        self.loaded = False
     50        self.manifest = ""
     51       
     52        if internal is None:
     53            internal = {}
     54        self.load()
     55        dict.__init__(self, internal)
     56        self.__initialised = True
     57   
     58    def __getattr__(self, item):
     59        """
     60        Simulates getting attributes
     61        """
     62        try:
     63            return self.__getitem__(item)
     64        except KeyError:
     65            return False
     66   
     67    def __setattr__(self, item, value):
     68        """
     69        Simulates setting attributes
     70        """
     71        if not self.__dict__.has_key('_Release__initialised'):
     72            return dict.__setattr__(self, item, value)
     73        elif self.__dict__.has_key(item):
     74            dict.__setattr__(self, item, value)
     75        else:
     76            self.__setitem__(item, value)
     77   
     78    def exists(self):
     79        """
     80        Returns true if the release already exists and could be loaded
     81        """
     82        return len(self)>0
     83   
     84    def load(self):
     85        """
     86        Loads metadata from release.py into itself
     87        """
     88        sys.path.insert(0, self.directory)
     89        os.chdir(self.directory)
     90        try:
     91            rel = __import__("release", {}, {}, [''])
     92            for info in dir(rel):
     93                if info == info.upper():
     94                    self[info] = str(getattr(rel, info))
     95        except (ImportError, AttributeError):
     96            return
     97        self.loaded = True
     98   
     99    def save(self, path, filename, data):
     100        """
     101        Saves given data to a file
     102        """
     103        filepath = os.path.join(path, filename)
     104        try:
     105            if os.path.isfile(filepath):
     106                filecontent = open(filepath, 'r').read()
     107                if filecontent == data:
     108                    return
     109            f = open(filepath, 'w')
     110            f.write(data)
     111            f.close()
     112        except OSError, e:
     113            raise CommandError(e)
     114        print "Written: %s" % filepath
     115   
     116    def check_path(self):
     117        """
     118        Moves an app directory if the app was renamed (except templates dir).
     119        """
     120        if self.renamed_name:
     121            old_path = os.path.join(self.directory, self.renamed_name)
     122            new_path = os.path.join(self.directory, self.NAME)
     123            try:
     124                shutil.move(old_path, new_path)
     125            except (IOError, OSError), e:
     126                raise CommandError(e)
     127            else:
     128                print "Moved: %r to %r" % (old_path, new_path)
     129                print "If necessary please move the templates manually."
     130            self.renamed_name = False
     131   
     132    def update(self, directories=DEFAULT_DIRECTORIES, files=DEFAULT_FILES):
     133        """
     134        Creates default directories and default files and should be called at
     135        the end of the assistent.
     136        """
     137        # check if the app was renamed and move it if yes
     138        self.check_path()
     139        # create default directories
     140       
     141        for newdir in directories:
     142            try:
     143                newpath = os.path.join(self.directory, newdir % self)
     144                if not os.path.exists(newpath):
     145                    os.makedirs(newpath)
     146                    print "Created: %s" % newpath
     147                elif not os.access(newpath, os.W_OK):
     148                    raise CommandError("You have no write access to the directory.")
     149            except OSError, e:
     150                raise CommandError(e)
     151            self.manifest += "recursive-include %s *\n" % newdir % self
     152       
     153        # write default files
     154        for newfile in files:
     155            if self.loaded and newfile[0].endswith(".txt"):
     156                continue
     157            self.save(self.directory, newfile[0], newfile[1] % self)
     158            self.manifest += "include %s\n" % newfile[0] % self
     159       
     160        # save manifest to file
     161        self.save(self.directory, "MANIFEST.in", self.manifest)
     162        self.loaded = True
     163
     164    def clean_up(self):
     165        """
     166        Helper function for file clean-up after interruption
     167        """
     168        try:
     169            shutil.rmtree(self.directory, True)
     170        except:
     171            pass
     172
     173def ask(prompt):
     174    return prompt.ask()
     175
     176def standalone_app(directory, default_name=None):
     177    """
     178    Helper function for creating a setup.py file for modules under the current
     179    workding dir. All arguments are required and will be prompted for if
     180    invalid or not given.
     181    """
     182    release = Release(directory)
     183    if default_name is not None and default_name.lower() in INVALID_APP_NAMES:
     184        release.clean_up(directory)
     185        raise CommandError("%r conflicts with the name of some package files and cannot be used as an app name. Please try another name." % default_name)
     186    if release.loaded:
     187        print "Django app found: %s (%s)." % (release.NAME, release.VERSION)
     188    try:
     189        name = Name(default_name or release.NAME or '').ask()
     190        # what if the name was changed during editapp?
     191        if name not in (release.NAME, default_name):
     192            release.renamed_name = release.NAME or default_name
     193        release.NAME = name
     194        release.URL = urlparse.urljoin(APP_REPOSITORY_URL, name)
     195        release.VERSION = Version(release.VERSION or '').ask()
     196        release.SUMMARY = Summary(release.SUMMARY or '').ask()
     197        release.KEYWORDS = Keywords(release.KEYWORDS or '').ask()
     198        release.AUTHOR = Author(release.AUTHOR or '').ask()
     199        release.AUTHOR_EMAIL = Email(release.AUTHOR_EMAIL or '').ask()
     200        release.ZIP_SAFE = ZipSafe(release.ZIP_SAFE or '').ask()
     201       
     202    except (KeyboardInterrupt, EOFError):
     203        # Delete directory if canceled
     204        if not release.loaded:
     205            clean_up(directory)
     206        print "\n"
     207        raise CommandError("Operation cancelled.")
     208    # Update the release with the new meta data
     209    release.update()
  • django/utils/package/prompts.py

     
     1from django.utils.package.validators import *
     2PYPI_KEYWORD = "django.apps"
     3
     4class Prompt(object):
     5    """Simple base class for prompting"""
     6    def __init__(self, default=None):
     7        self.default = default
     8        self.title = self.__class__.__name__
     9        self.preflight()
     10        self.setup()
     11   
     12    def setup(self):
     13        "sets up the user dialog"
     14        self.question = self.title
     15        if self.default is not None:
     16            self.question += ' (%r)' % self.default
     17        self.question += ': '
     18   
     19    def ask(self):
     20        "main loop for user input"
     21        while 1:
     22            response = raw_input(self.question).strip()
     23            if not response:
     24                if self.default is not None:
     25                    response = self.default
     26            if self.validate(response):
     27                return self.postflight(response)
     28   
     29    def preflight(self):
     30        "can be used to manipulate the default data"
     31        pass
     32   
     33    def validate(self, response):
     34        "validates user response against validators"
     35        return isgiven(response)
     36   
     37    def postflight(self, response):
     38        "can be used to manipulate the response"
     39        return response
     40
     41class Name(Prompt):
     42    "the application and directory name"
     43    def validate(self, response):
     44        response = safe_name(response)
     45        return isalnum(response) and isvalidname(response)
     46
     47class Version(Prompt):
     48    "the version, validated against pkg_resources"
     49    def validate(self, response):
     50        response = safe_version(response)
     51        return isvalidversion(response)
     52       
     53class Keywords(Prompt):
     54    "the keywords, includes the default PyPI keyword"
     55    def preflight(self):
     56        keywordlist = find_keywords_re.findall(self.default)
     57        if PYPI_KEYWORD in keywordlist:
     58            keywordlist.remove(PYPI_KEYWORD)
     59            self.default = " ".join(keywordlist).strip()
     60   
     61    def validate(self, response):
     62        return isgiven(response) and iskeywordlist(response)
     63   
     64    def postflight(self, response):
     65        keywordlist = find_keywords_re.findall(response)
     66        keywordlist.insert(0,PYPI_KEYWORD)
     67        return " ".join(keywordlist).strip()
     68
     69class Email(Prompt):
     70    "e-mail adress of the application author"
     71    def validate(self, response):
     72        return isgiven(response) and isemailadress(response)
     73
     74class ZipSafe(Prompt):
     75    "defines if the egg distribution can be a zipped file while installation"
     76    def preflight(self):
     77        if self.default.lower() in ("true", "false"):
     78            self.default = {'true':'yes','false':'no'}[self.default.lower()]
     79   
     80    def validate(self, response):
     81        return isyesorno(response)
     82   
     83    def postflight(self, response):
     84        return {'yes':True,'no':False}[response]
     85
     86class Author(Prompt):
     87    "name of the app author and owner"
     88    pass
     89
     90class Summary(Prompt):
     91    "short summary about the app"
     92    pass
  • django/utils/package/templates/INSTALL.txt

     
     1Thanks for downloading "%(NAME)s".
     2
     3To install it, run the following command inside this directory:
     4
     5    python setup.py install
     6
     7Or if you'd prefer you can use any other setuptools function, or simply
     8place the included ``%(NAME)s`` directory somewhere on your Python path.
     9
     10Note that this application requires Python 2.3 or later, and Django
     110.97 or later. You can obtain Python from http://www.python.org/ and
     12Django from http://www.djangoproject.com/.
  • django/utils/package/templates/release.py

     
     1# Metadata used for packaging, handle with care
     2NAME = "%(NAME)s"
     3VERSION = "%(VERSION)s"
     4URL = "%(URL)s"
     5AUTHOR = "%(AUTHOR)s"
     6AUTHOR_EMAIL = "%(AUTHOR_EMAIL)s"
     7SUMMARY = "%(SUMMARY)s"
     8KEYWORDS = "%(KEYWORDS)s"
     9ZIP_SAFE = %(ZIP_SAFE)s
  • django/utils/package/templates/setup.py

     
     1from setuptools import find_packages
     2from django.utils.package import setup
     3
     4try:
     5    import release
     6except ImportError:
     7    raise "Please add a release.py file to the application directory."
     8
     9setup(
     10    name = release.NAME,
     11    version = release.VERSION,
     12    url = release.URL,
     13    author = release.AUTHOR,
     14    author_email = release.AUTHOR_EMAIL,
     15    summary = release.SUMMARY,
     16    zip_safe = release.ZIP_SAFE,
     17    keywords = release.KEYWORDS,
     18    packages = find_packages(),
     19    include_package_data = True,
     20)
  • django/utils/package/templates/README.txt

     
     1%(NAME)s
     2==============================================================================
     3
     4TODO
  • extras/django_bash_completion

     
    4242    prev="${COMP_WORDS[COMP_CWORD-1]}"
    4343
    4444    # Standalone options
    45     opts="--help --settings --pythonpath --noinput --noreload --format --indent --verbosity --adminmedia --version"
     45    opts="--help --settings --pythonpath --noinput --noreload --noskeleton --format --indent --verbosity --adminmedia --version"
    4646    # Actions
    4747    actions="adminindex createcachetable dbshell diffsettings \
    4848             dumpdata flush inspectdb loaddata reset runfcgi runserver \
  • docs/tutorial01.txt

     
    220220To create your app, make sure you're in the ``mysite`` directory and type
    221221this command::
    222222
    223     python manage.py startapp polls
     223    python manage.py --noskeleton startapp polls
    224224
    225225That'll create a directory ``polls``, which is laid out like this::
    226226
  • docs/tutorial03.txt

     
    418418with minimal fuss.
    419419
    420420Our poll app is pretty decoupled at this point, thanks to the strict directory
    421 structure that ``python manage.py startapp`` created, but one part of it is
    422 coupled to the Django settings: The URLconf.
     421structure that ``python manage.py --noskeleton startapp`` created, but one
     422part of it is coupled to the Django settings: The URLconf.
    423423
    424424We've been editing the URLs in ``mysite/urls.py``, but the URL design of an
    425425app is specific to the app, not to the Django installation -- so let's move the
  • docs/man/django-admin.1

     
    8787Prints the SQL statements for resetting PostgreSQL sequences for the
    8888given app name(s).
    8989.TP
    90 .BI "startapp [" "appname" "]"
     90.BI "startapp [" "\-\-noskeleton" "] [" "appname" "]"
    9191Creates a Django app directory structure for the given app name in
    9292the current directory.
     93.BI \-\-noskeleton
     94option disables the assistent for creating reusable Django apps.
    9395.TP
    9496.BI "startproject [" "projectname" "]"
    9597Creates a Django project directory structure for the given project name
  • docs/django-admin.txt

     
    505505Creates a Django app directory structure for the given app name in the current
    506506directory.
    507507
     508Turning off the metadata assistent
     509~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     510
     511Use the ``--noskeleton`` option to disable the assistent which asks for
     512metadata to create reusable Django apps. This means you won't be asked for
     513detailed information about the app you are going to create and no additional
     514files will be created.
     515
    508516startproject <projectname>
    509517--------------------------
    510518
Back to Top