Skip to content

Commit b193419

Browse files
committed
Add option use_system_packages, allowing to use a virtualenv with the --system-site-packages option (close #218).
1 parent fd9e9a8 commit b193419

File tree

4 files changed

+161
-4
lines changed

4 files changed

+161
-4
lines changed

readthedocs/projects/forms.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ class ImportProjectForm(ProjectForm):
5555

5656
class Meta:
5757
model = Project
58-
fields = ('name', 'repo', 'repo_type', 'description', 'project_url', 'tags', 'default_branch', 'default_version', 'use_virtualenv', 'conf_py_file', 'requirements_file', 'analytics_code', 'documentation_type')
58+
fields = ('name', 'repo', 'repo_type', 'description', 'project_url',
59+
'tags', 'default_branch', 'default_version', 'use_virtualenv',
60+
'use_system_packages', 'conf_py_file', 'requirements_file',
61+
'analytics_code', 'documentation_type')
5962

6063
def clean_repo(self):
6164
repo = self.cleaned_data.get('repo', '').strip()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# -*- coding: utf-8 -*-
2+
import datetime
3+
from south.db import db
4+
from south.v2 import SchemaMigration
5+
from django.db import models
6+
7+
8+
class Migration(SchemaMigration):
9+
10+
def forwards(self, orm):
11+
# Adding field 'Project.use_system_packages'
12+
db.add_column('projects_project', 'use_system_packages',
13+
self.gf('django.db.models.fields.BooleanField')(default=False),
14+
keep_default=False)
15+
16+
def backwards(self, orm):
17+
# Deleting field 'Project.use_system_packages'
18+
db.delete_column('projects_project', 'use_system_packages')
19+
20+
models = {
21+
'auth.group': {
22+
'Meta': {'object_name': 'Group'},
23+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
24+
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
25+
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
26+
},
27+
'auth.permission': {
28+
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
29+
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
30+
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
31+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
32+
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
33+
},
34+
'auth.user': {
35+
'Meta': {'object_name': 'User'},
36+
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
37+
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
38+
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
39+
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
40+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
41+
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
42+
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
43+
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
44+
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
45+
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
46+
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
47+
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
48+
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
49+
},
50+
'contenttypes.contenttype': {
51+
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
52+
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
53+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
54+
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
55+
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
56+
},
57+
'projects.file': {
58+
'Meta': {'ordering': "('denormalized_path',)", 'object_name': 'File'},
59+
'content': ('django.db.models.fields.TextField', [], {}),
60+
'denormalized_path': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
61+
'heading': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
62+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
63+
'ordering': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '1'}),
64+
'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'children'", 'null': 'True', 'to': "orm['projects.File']"}),
65+
'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'files'", 'to': "orm['projects.Project']"}),
66+
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
67+
'status': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '1'})
68+
},
69+
'projects.filerevision': {
70+
'Meta': {'ordering': "('-revision_number',)", 'object_name': 'FileRevision'},
71+
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
72+
'created_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
73+
'diff': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
74+
'file': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'revisions'", 'to': "orm['projects.File']"}),
75+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
76+
'is_reverted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
77+
'revision_number': ('django.db.models.fields.IntegerField', [], {})
78+
},
79+
'projects.importedfile': {
80+
'Meta': {'object_name': 'ImportedFile'},
81+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
82+
'md5': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
83+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
84+
'path': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
85+
'project': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'imported_files'", 'to': "orm['projects.Project']"}),
86+
'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'})
87+
},
88+
'projects.project': {
89+
'Meta': {'ordering': "('slug',)", 'object_name': 'Project'},
90+
'analytics_code': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True', 'blank': 'True'}),
91+
'conf_py_file': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '255', 'blank': 'True'}),
92+
'copyright': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
93+
'crate_url': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
94+
'default_branch': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
95+
'default_version': ('django.db.models.fields.CharField', [], {'default': "'latest'", 'max_length': '255'}),
96+
'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
97+
'django_packages_url': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
98+
'documentation_type': ('django.db.models.fields.CharField', [], {'default': "'sphinx'", 'max_length': '20'}),
99+
'featured': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
100+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
101+
'modified_date': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
102+
'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
103+
'path': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
104+
'project_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
105+
'pub_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
106+
'related_projects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['projects.Project']", 'null': 'True', 'through': "orm['projects.ProjectRelationship']", 'blank': 'True'}),
107+
'repo': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
108+
'repo_type': ('django.db.models.fields.CharField', [], {'default': "'git'", 'max_length': '10'}),
109+
'requirements_file': ('django.db.models.fields.CharField', [], {'default': 'None', 'max_length': '255', 'null': 'True', 'blank': 'True'}),
110+
'skip': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
111+
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '255'}),
112+
'suffix': ('django.db.models.fields.CharField', [], {'default': "'.rst'", 'max_length': '10'}),
113+
'theme': ('django.db.models.fields.CharField', [], {'default': "'default'", 'max_length': '20'}),
114+
'use_system_packages': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
115+
'use_virtualenv': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
116+
'users': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'projects'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
117+
'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
118+
},
119+
'projects.projectrelationship': {
120+
'Meta': {'object_name': 'ProjectRelationship'},
121+
'child': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'superprojects'", 'to': "orm['projects.Project']"}),
122+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
123+
'parent': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'subprojects'", 'to': "orm['projects.Project']"})
124+
},
125+
'taggit.tag': {
126+
'Meta': {'object_name': 'Tag'},
127+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
128+
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
129+
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
130+
},
131+
'taggit.taggeditem': {
132+
'Meta': {'object_name': 'TaggedItem'},
133+
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}),
134+
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
135+
'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
136+
'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"})
137+
}
138+
}
139+
140+
complete_apps = ['projects']

readthedocs/projects/models.py

+2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ class Project(models.Model):
8585
skip = models.BooleanField(_('Skip'))
8686
use_virtualenv = models.BooleanField(_('Use virtualenv'),
8787
help_text=_("Install your project inside a virtualenv using setup.py install"))
88+
use_system_packages = models.BooleanField(_('Use system packages'),
89+
help_text=_("Give the virtual environment access to the global sites-packages dir"))
8890
django_packages_url = models.CharField(_('Django Packages URL'), max_length=255, blank=True)
8991
crate_url = models.CharField(_('Crate URL'), max_length=255, blank=True)
9092

readthedocs/projects/tasks.py

+15-3
Original file line numberDiff line numberDiff line change
@@ -233,11 +233,23 @@ def update_imported_docs(project, version):
233233

234234
#Do Virtualenv bits:
235235
if project.use_virtualenv:
236-
update_docs_output['venv'] = run('{cmd} --distribute --no-site-packages {path}'.format(
236+
if project.use_system_packages:
237+
site_packages = '--system-site-packages'
238+
else:
239+
site_packages = '--no-site-packages'
240+
update_docs_output['venv'] = run('{cmd} --distribute {site_packages} {path}'.format(
237241
cmd='virtualenv',
242+
site_packages=site_packages,
238243
path=project.venv_path(version=version_slug)))
239-
update_docs_output['sphinx'] = run('{cmd} install -U hg+http://bitbucket.org/birkenfeld/sphinx/@d4c6ac1fcc9c#egg=Sphinx virtualenv==1.8.2 distribute==0.6.28 docutils==0.8.1'.format(
240-
cmd=project.venv_bin(version=version_slug, bin='pip')))
244+
# Other code expects sphinx-build to be installed inside the virtualenv.
245+
# Using the -I option makes sure it gets installed even if it is
246+
# already installed system-wide (and --system-site-packages is used)
247+
if project.use_system_packages:
248+
ignore_option = '-I'
249+
else:
250+
ignore_option = ''
251+
update_docs_output['sphinx'] = run('{cmd} install -U {ignore_option} hg+http://bitbucket.org/birkenfeld/sphinx/@d4c6ac1fcc9c#egg=Sphinx virtualenv==1.8.2 distribute==0.6.28 docutils==0.8.1'.format(
252+
cmd=project.venv_bin(version=version_slug, bin='pip'), ignore_option=ignore_option))
241253

242254
if project.requirements_file:
243255
os.chdir(project.checkout_path(version_slug))

0 commit comments

Comments
 (0)