aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRune Halvorsen <runeh@vorkosigan.(none)>2009-05-03 21:41:11 +0200
committerRune Halvorsen <runeh@vorkosigan.(none)>2009-05-03 21:41:11 +0200
commit1804d0cfb72d766f16aaa1e11f48084f179fc16c (patch)
tree341f6fea72017f497785381e6b05f25267091905
parent846251f44cee277f5f35e7374cf2755e0e57a4ca (diff)
downloadchishop-1804d0cfb72d766f16aaa1e11f48084f179fc16c.tar.bz2
chishop-1804d0cfb72d766f16aaa1e11f48084f179fc16c.tar.xz
chishop-1804d0cfb72d766f16aaa1e11f48084f179fc16c.zip
Added management command for easy_installing into the chishop
-rw-r--r--buildout.cfg4
-rw-r--r--djangopypi/management/__init__.py0
-rw-r--r--djangopypi/management/commands/__init__.py0
-rw-r--r--djangopypi/management/commands/ppadd.py143
-rw-r--r--djangopypi/models.py10
5 files changed, 152 insertions, 5 deletions
diff --git a/buildout.cfg b/buildout.cfg
index 925ed6a..fc36b3c 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -1,6 +1,6 @@
1[buildout] 1[buildout]
2parts = django 2parts = django
3eggs = 3eggs = pkginfo
4 4
5[django] 5[django]
6recipe = djangorecipe 6recipe = djangorecipe
@@ -8,4 +8,4 @@ version = 1.0.2
8settings = development 8settings = development
9eggs = ${buildout:eggs} 9eggs = ${buildout:eggs}
10project = chishop 10project = chishop
11wsgi = true \ No newline at end of file 11wsgi = true
diff --git a/djangopypi/management/__init__.py b/djangopypi/management/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/djangopypi/management/__init__.py
diff --git a/djangopypi/management/commands/__init__.py b/djangopypi/management/commands/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/djangopypi/management/commands/__init__.py
diff --git a/djangopypi/management/commands/ppadd.py b/djangopypi/management/commands/ppadd.py
new file mode 100644
index 0000000..78eb2cf
--- /dev/null
+++ b/djangopypi/management/commands/ppadd.py
@@ -0,0 +1,143 @@
1"""
2Management command for adding a package to the repository. Supposed to be the
3equivelant of calling easy_install, but the install target is the chishop.
4"""
5
6from __future__ import with_statement
7import os
8import tempfile
9import shutil
10import urllib
11
12import pkginfo
13
14from django.core.files.base import File
15from django.core.management.base import LabelCommand
16from optparse import make_option
17from contextlib import contextmanager
18from urlparse import urlsplit
19from setuptools.package_index import PackageIndex
20from django.contrib.auth.models import User
21from djangopypi.models import Project, Release, Classifier
22
23
24
25
26
27@contextmanager
28def tempdir():
29 """Simple context that provides a temporary directory that is deleted
30 when the context is exited."""
31 d = tempfile.mkdtemp(".tmp", "djangopypi.")
32 yield d
33 shutil.rmtree(d)
34
35class Command(LabelCommand):
36 option_list = LabelCommand.option_list + (
37 make_option("-o", "--owner", help="add packages as OWNER",
38 metavar="OWNER", default=None),
39 )
40 help = """Add one or more packages to the repository. Each argument can
41be a package name or a URL to an archive or egg. Package names honour
42the same rules as easy_install with regard to indicating versions etc.
43
44If a version of the package exists, but is older than what we want to install,
45the owner remains the same.
46
47For new packages there needs to be an owner. If the --owner option is present
48we use that value. If not, we try to match the maintainer of the package, form
49the metadata, with a user in out database, based on the If it's a new package
50and the maintainer emailmatches someone in our user list, we use that. If not,
51the package can not be
52added"""
53
54 def __init__(self, *args, **kwargs):
55 self.pypi = PackageIndex()
56 LabelCommand.__init__(self, *args, **kwargs)
57
58 def handle_label(self, label, **options):
59 with tempdir() as tmp:
60 path = self.pypi.download(label, tmp)
61 if path:
62 self._save_package(path, options["owner"])
63 else:
64 print "Could not add %s. Not found." % label
65
66 def _save_package(self, path, ownerid):
67 meta = self._get_meta(path)
68
69 try:
70 # can't use get_or_create as that demands there be an owner
71 project = Project.objects.get(name=meta.name)
72 isnewproject = False
73 except Project.DoesNotExist:
74 project = Project(name=meta.name)
75 isnewproject = True
76
77 release = project.get_release(meta.version)
78 if not isnewproject and release and release.version == meta.version:
79 print "%s-%s already added" % (meta.name, meta.version)
80 return
81
82 # algorithm as follows: If owner is given, try to grab user with that
83 # username from db. If doesn't exist, bail. If no owner set look at
84 # mail address from metadata and try to get that user. If it exists
85 # use it. If not, bail.
86 owner = None
87
88 if ownerid:
89 try:
90 if "@" in ownerid:
91 owner = User.objects.get(email=ownerid)
92 else:
93 owner = User.objects.get(username=ownerid)
94 except User.DoesNotExist:
95 pass
96 else:
97 try:
98 owner = User.objects.get(email=meta.author_email)
99 except User.DoesNotExist:
100 pass
101
102 if not owner:
103 print "No owner defined. Use --owner to force one"
104 return
105
106 # at this point we have metadata and an owner, can safely add it.
107
108 project.owner = owner
109 # Some packages don't have proper licence, seems to be a problem
110 # with setup.py upload. Use "UNKNOWN"
111 project.license = meta.license or "Unknown"
112 project.metadata_version = meta.metadata_version
113 project.author = meta.author
114 project.home_page = meta.home_page
115 project.download_url = meta.download_url
116 project.summary = meta.summary
117 project.description = meta.description
118 project.author_email = meta.author_email
119
120 project.save()
121
122 for classifier in meta.classifiers:
123 project.classifiers.add(
124 Classifier.objects.get_or_create(name=classifier)[0])
125
126 release = Release()
127 release.version = meta.version
128 release.project = project
129 filename = os.path.basename(path)
130
131 file = File(open(path, "rb"))
132 release.distribution.save(filename, file)
133 release.save()
134 print "%s-%s added" % (meta.name, meta.version)
135
136 def _get_meta(self, path):
137 if path.endswith((".zip", ".tar.gz")):
138 return pkginfo.SDist(path)
139 elif path.endswith(".egg"):
140 return pkginfo.BDist(path)
141 else:
142 print "Couldn't get metadata from %s. Not added to chishop" % os.path.basename(path)
143 return None
diff --git a/djangopypi/models.py b/djangopypi/models.py
index d6df975..8ebed5e 100644
--- a/djangopypi/models.py
+++ b/djangopypi/models.py
@@ -14,7 +14,7 @@ modification, are permitted provided that the following conditions are met:
14 14
15Neither the name of Ask Solem nor the names of its contributors may be used 15Neither the name of Ask Solem nor the names of its contributors may be used
16to endorse or promote products derived from this software without specific 16to endorse or promote products derived from this software without specific
17prior written permission. 17prior written permission.
18 18
19THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 20AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
@@ -104,6 +104,12 @@ class Project(models.Model):
104 def get_pypi_absolute_url(self): 104 def get_pypi_absolute_url(self):
105 return ('djangopypi-pypi_show_links', (), {'dist_name': self.name}) 105 return ('djangopypi-pypi_show_links', (), {'dist_name': self.name})
106 106
107 def get_release(self, version):
108 """Return the release object for version, or None"""
109 try:
110 self.releases.get(version=version)
111 except Release.DoesNotExist:
112 return None
107 113
108class Release(models.Model): 114class Release(models.Model):
109 version = models.CharField(max_length=128) 115 version = models.CharField(max_length=128)
@@ -152,5 +158,3 @@ class Release(models.Model):
152 158
153 def get_dl_url(self): 159 def get_dl_url(self):
154 return "%s#md5=%s" % (self.distribution.url, self.md5_digest) 160 return "%s#md5=%s" % (self.distribution.url, self.md5_digest)
155
156