Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Support for external base projects. #34

Closed
wants to merge 5 commits into from

4 participants

@nrb

These commits add support for using git and hg pip editables, as well as plain directories to the setup_project -b option.

@lukeman lukeman closed this
@nisaacson

Can you give an example of a live project that can be installed in this manner?

I am trying to create a new project using the latest dev branch of pinax-project-account and cannot see how to do this from the https://github.com/pinax/pinax-project-account page

see http://stackoverflow.com/questions/10804923/how-can-i-install-external-pinax-projects for more

Sorry, I can't; this pull request is actually deprecated in favor of a different implementation. I haven't been too involved in the project for a few months now, you may want to check on #pinax in IRC to see if they have made any progress.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 9, 2011
  1. @brosner
Commits on Oct 22, 2011
  1. @nrb
Commits on Nov 9, 2011
  1. @nrb
  2. @nrb
Commits on Nov 11, 2011
  1. @nrb
This page is out of date. Refresh to see the latest.
View
11 docs/starterprojects.txt
@@ -156,3 +156,14 @@ the Django templating language. It uses ``pinax.views.static_view`` mounted
at ``/``. For example if you access ``/test.html`` it will render
``templates/test.html``. Directory paths, i.e., ``/a/``, will render
``/templates/a/index.html``.
+
+External Starter Projects
+=========================
+
+The Pinax ``setup_project`` command can also use starter projects built by third parties.
+These can either be plain directory structures, or they may be a git/hg pip editable.
+
+To install a starter project from an external source, simply pass the file path or git/hg
+URL to the ``-b`` option::
+
+ pinax-admin setup_project -b git+git://github.com/user/project.git#egg=project my_new_project
View
100 pinax/core/management/commands/setup_project.py
@@ -5,8 +5,13 @@
import re
import shutil
import sys
+import urlparse
import pip
+from pip.index import PackageFinder
+from pip.locations import build_prefix, src_prefix
+from pip.req import InstallRequirement, RequirementSet
+from pip.vcs import vcs
try:
from pip.exceptions import InstallationError
@@ -32,12 +37,12 @@ class Command(BaseCommand):
optparse.make_option("-l", "--list-bases",
dest = "list_bases",
action = "store_true",
- help = "lists the starter projects (bases) that are available"
+ help = "lists the bundled starter projects (bases) that are available"
),
optparse.make_option("-b", "--base",
dest = "base",
default = "zero",
- help = "the starter project to use as a base (excluding _project, e.g., basic or social. see --list-projects)"
+ help = "the starter project to use as a base (excluding _project, e.g., basic or social. see --list-projects for included starter projects). Valid git/hg PIP editable strings and plain file paths are accepted, as well."
),
optparse.make_option("--no-reqs",
dest = "no_reqs",
@@ -113,15 +118,11 @@ def setup_project(self, destination, base, options):
# allow repos and such)
if base in [p.replace("_project", "") for p in self.project_list()]:
project_name = "%s_project" % base
- source = os.path.join(PROJECTS_DIR, project_name)
+ source = "file+file://%s" % os.path.join(PROJECTS_DIR, project_name)
else:
- if not os.path.exists(base):
- raise CommandError(
- "Project template does not exist the given "
- "path: %s" % base
- )
- else:
- project_name = os.path.basename(base)
+ project_name = user_project_name
+ source = base
+
installer = ProjectInstaller(source, destination, project_name, user_project_name)
installer.copy()
@@ -146,22 +147,85 @@ class ProjectInstaller(object):
Provides the methods to install a project at a given destination
"""
- def __init__(self, source_dir, project_dir, project_name, user_project_name):
- self.source_dir = source_dir
- self.project_dir = project_dir
+ @classmethod
+ def clean_source(cls, source):
+ if os.path.exists(source):
+ kind, url = "file", source
+ else:
+ kind, url = source.split("+", 1)
+ source = urlparse.urlparse(url)
+
+ if kind not in ["file", "git", "hg"]:
+ raise CommandError("project base is invalid")
+
+ if kind == "file":
+ source = os.path.abspath(source)
+
+ return kind, source
+
+ def __init__(self, source, project_dir, project_name, user_project_name):
+ self.kind, self.source = self.clean_source(source)
+ self.project_dir = os.path.join(os.getcwd(), project_dir)
self.project_name = project_name
self.user_project_name = user_project_name
+
+ if self.kind in ["git", "hg"]:
+ # Extract the name of the installed egg from the provided URL.
+ self.egg_name = source.rsplit("#egg=", 1)[1]
+
+ def parse_source(self, source):
+ kind, url = source.split("+", 1)
+ return kind, urlparse.urlparse(url)
def generate_secret_key(self):
chars = "abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)"
return "".join([random.choice(chars) for i in xrange(50)])
def copy(self):
- copytree(self.source_dir, self.project_dir,
- excluded_patterns=[
- ".svn", ".pyc", "dev.db"
- ]
- )
+ if self.kind in ["git", "hg"]:
+ # Let pip import version control information.
+ pip.version_control()
+
+ reqset = RequirementSet(
+ build_dir=build_prefix,
+ src_dir=src_prefix,
+ download_dir=None
+ )
+
+ # Let pip do all the heavy lifting for VCS-based packages.
+ req = InstallRequirement.from_editable(
+ self.source.geturl(),
+ default_vcs=self.kind
+ )
+ reqset.add_requirement(req)
+
+ finder = PackageFinder(find_links=[], index_urls=[])
+
+ reqset.prepare_files(finder)
+ reqset.install(install_options=[], global_options=[])
+ reqset.cleanup_files()
+
+ # Try to build a path to the newly installed package.
+ installed_path = os.path.join(src_prefix, self.egg_name, self.egg_name)
+
+ # A bit of a hack, but most commonly package names replace dashes with underscores.
+ if not os.path.exists(installed_path):
+ package_name = self.egg_name.replace("-", "_")
+ installed_path = os.path.join(src_prefix, self.egg_name, package_name)
+
+ copytree(installed_path, self.project_dir,
+ excluded_patterns=[
+ ".git", ".gitignore", ".hg", ".hgignore", ".pyc", "dev.db"
+ ]
+ )
+ elif self.kind == "file":
+ copytree(self.source, self.project_dir,
+ excluded_patterns=[
+ ".svn", ".pyc", "dev.db"
+ ]
+ )
+ else:
+ raise Exception("unsupported kind")
def fix_settings(self):
# @@@ settings refactor
Something went wrong with that request. Please try again.