class TestPublicSymlinkSingleVersion(TestCase): def setUp(self): self.project = get(Project, slug="kong") self.version = get(Version, verbose_name="latest", active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = {"project_root": self.symlink.project_root, "doc_path": self.project.rtd_build_path()} self.commands = [] @patched def test_symlink_single_version(self): self.symlink.symlink_single_version() commands = ["ln -nsf {doc_path}/ {project_root}"] for index, command in enumerate(commands): self.assertEqual(self.commands[index], command.format(**self.args)) @patched def test_symlink_single_version_missing(self): project = get(Project) project.versions.update(privacy_level="private") symlink = PublicSymlink(project) # Set because *something* triggers project symlinking on get(Project) self.commands = [] symlink.symlink_single_version() self.assertEqual([], self.commands)
def test_symlink_single_version_missing(self): project = get(Project) project.versions.update(privacy_level="private") symlink = PublicSymlink(project) # Set because *something* triggers project symlinking on get(Project) self.commands = [] symlink.symlink_single_version() self.assertEqual([], self.commands)
class TestPublicSymlinkUnicode(TempSiterootCase, TestCase): def setUp(self): super(TestPublicSymlinkUnicode, self).setUp() self.project = get(Project, slug='kong', name=u'foo-∫', main_language_project=None) self.project.save() self.stable = get(Version, slug='foo-a', verbose_name=u'foo-∂', active=True, project=self.project) self.symlink = PublicSymlink(self.project) def test_symlink_no_error(self): try: self.symlink.run() except: self.fail('Symlink run raised an exception on unicode slug')
class TestPublicSymlinkUnicode(TestCase): def setUp(self): self.project = get(Project, slug="kong", name=u"foo-∫") self.stable = get(Version, slug="stable", verbose_name=u"foo-∂", active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = { "project_root": self.symlink.project_root, "latest_path": self.project.rtd_build_path("latest"), "stable_path": self.project.rtd_build_path("stable"), } self.commands = [] @patched def test_symlink_no_error(self): # Don't raise an error. self.symlink.run() self.assertTrue(True)
class TestSymlinkCnames(TestCase): def setUp(self): self.project = get(Project, slug="kong") self.version = get(Version, verbose_name="latest", active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = {"cname_root": self.symlink.CNAME_ROOT, "project_root": self.symlink.project_root} self.commands = [] @patched def test_symlink_cname(self): self.cname = get(Domain, project=self.project, url="http://woot.com", cname=True) self.symlink.symlink_cnames() self.args["cname"] = self.cname.domain commands = ["ln -nsf {project_root} {cname_root}/{cname}"] for index, command in enumerate(commands): self.assertEqual(self.commands[index], command.format(**self.args))
def setUp(self): super(TestPublicSymlinkUnicode, self).setUp() self.project = get(Project, slug='kong', name=u'foo-∫', main_language_project=None) self.project.save() self.stable = get(Version, slug='foo-a', verbose_name=u'foo-∂', active=True, project=self.project) self.symlink = PublicSymlink(self.project)
def setUp(self): self.project = get(Project, slug='kong') self.version = get(Version, verbose_name='latest', active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = { 'project_root': self.symlink.project_root, 'doc_path': self.project.rtd_build_path(), } self.commands = []
def setUp(self): self.project = get(Project, slug='kong') self.version = get(Version, verbose_name='latest', active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = { 'cname_root': self.symlink.CNAME_ROOT, 'project_root': self.symlink.project_root, } self.commands = []
def setUp(self): self.project = get(Project, slug="kong", name=u"foo-∫") self.stable = get(Version, slug="stable", verbose_name=u"foo-∂", active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = { "project_root": self.symlink.project_root, "latest_path": self.project.rtd_build_path("latest"), "stable_path": self.project.rtd_build_path("stable"), } self.commands = []
class TestPublicSymlinkUnicode(TestCase): def setUp(self): self.project = get(Project, slug='kong', name=u'foo-∫') self.stable = get( Version, slug='stable', verbose_name=u'foo-∂', active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = { 'project_root': self.symlink.project_root, 'latest_path': self.project.rtd_build_path('latest'), 'stable_path': self.project.rtd_build_path('stable'), } self.commands = [] @patched def test_symlink_no_error(self): # Don't raise an error. self.symlink.run() self.assertTrue(True)
def setUp(self): self.project = get(Project, slug='kong', name=u'foo-∫') self.stable = get( Version, slug='stable', verbose_name=u'foo-∂', active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = { 'project_root': self.symlink.project_root, 'latest_path': self.project.rtd_build_path('latest'), 'stable_path': self.project.rtd_build_path('stable'), } self.commands = []
class TestPublicSymlinkSingleVersion(TestCase): def setUp(self): self.project = get(Project, slug='kong') self.version = get(Version, verbose_name='latest', active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = { 'project_root': self.symlink.project_root, 'doc_path': self.project.rtd_build_path(), } self.commands = [] @patched def test_symlink_single_version(self): self.symlink.symlink_single_version() commands = [ 'ln -nsf {doc_path}/ {project_root}', ] for index, command in enumerate(commands): self.assertEqual(self.commands[index], command.format(**self.args))
class TestPublicSymlinkVersions(BaseSymlinkVersions, TestCase): def setUp(self): self.project = get(Project, slug="kong") self.stable = get(Version, slug="stable", verbose_name="stable", active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = { "project_root": self.symlink.project_root, "latest_path": self.project.rtd_build_path("latest"), "stable_path": self.project.rtd_build_path("stable"), } self.commands = [] @patched def test_no_symlink_private_versions(self): self.stable.privacy_level = "private" self.stable.save() self.symlink.symlink_versions() commands = ["ln -nsf {latest_path} {project_root}/en/latest"] for index, command in enumerate(commands): self.assertEqual(self.commands[index], command.format(**self.args)) def test_removed_versions(self): version_link = os.path.join(self.symlink.project_root, "en", self.stable.slug) self.symlink.symlink_versions() self.assertTrue(os.path.lexists(version_link)) self.stable.privacy_level = "private" self.stable.save() self.symlink.symlink_versions() self.assertTrue(not os.path.lexists(version_link))
def robots_txt(request, project): """ Serve custom user's defined ``/robots.txt``. If the user added a ``robots.txt`` in the "default version" of the project, we serve it directly. """ # Use the ``robots.txt`` file from the default version configured version_slug = project.get_default_version() version = project.versions.get(slug=version_slug) no_serve_robots_txt = any([ # If project is private or, project.privacy_level == constants.PRIVATE, # default version is private or, version.privacy_level == constants.PRIVATE, # default version is not active or, not version.active, # default version is not built not version.built, ]) if no_serve_robots_txt: # ... we do return a 404 raise Http404() filename = resolve_path( project, version_slug=version_slug, filename='robots.txt', subdomain= True, # subdomain will make it a "full" path without a URL prefix ) # This breaks path joining, by ignoring the root when given an "absolute" path if filename[0] == '/': filename = filename[1:] basepath = PublicSymlink(project).project_root fullpath = os.path.join(basepath, filename) if os.path.exists(fullpath): return HttpResponse(open(fullpath).read(), content_type='text/plain') sitemap_url = '{scheme}://{domain}/sitemap.xml'.format( scheme='https', domain=project.subdomain(), ) return HttpResponse( 'User-agent: *\nAllow: /\nSitemap: {}\n'.format(sitemap_url), content_type='text/plain', )
class TestSymlinkCnames(TestCase): def setUp(self): self.project = get(Project, slug='kong') self.version = get(Version, verbose_name='latest', active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = { 'cname_root': self.symlink.CNAME_ROOT, 'project_root': self.symlink.project_root, } self.commands = [] @patched def test_symlink_cname(self): self.cname = get(Domain, project=self.project, url='http://woot.com', cname=True) self.symlink.symlink_cnames() self.args['cname'] = self.cname.domain commands = [ 'ln -nsf {project_root} {cname_root}/{cname}', ] for index, command in enumerate(commands): self.assertEqual(self.commands[index], command.format(**self.args))
def resolve_404_path(project, version_slug=None, language=None, filename='404.html'): """ Helper to resolve the path of ``404.html`` for project. The resolution is based on ``project`` object, version slug and language. :returns: tuple containing the (basepath, filename) :rtype: tuple """ filename = resolve_path( project, version_slug=version_slug, language=language, filename=filename, subdomain= True, # subdomain will make it a "full" path without a URL prefix ) # This breaks path joining, by ignoring the root when given an "absolute" path if filename[0] == '/': filename = filename[1:] version = None if version_slug: version_qs = project.versions.filter(slug=version_slug) if version_qs.exists(): version = version_qs.first() private = any([ version and version.privacy_level == PRIVATE, not version and project.privacy_level == PRIVATE, ]) if private: symlink = PrivateSymlink(project) else: symlink = PublicSymlink(project) basepath = symlink.project_root fullpath = os.path.join(basepath, filename) return (basepath, filename, fullpath)
def _serve_symlink_docs(request, project, privacy_level, filename=''): # Handle indexes if filename == '' or filename[-1] == '/': filename += 'index.html' # This breaks path joining, by ignoring the root when given an "absolute" path if filename[0] == '/': filename = filename[1:] log.info('Serving %s for %s' % (filename, project)) files_tried = [] serve_docs = getattr(settings, 'SERVE_DOCS', [constants.PRIVATE]) if (settings.DEBUG or constants.PUBLIC in serve_docs) and privacy_level != constants.PRIVATE: public_symlink = PublicSymlink(project) basepath = public_symlink.project_root if os.path.exists(os.path.join(basepath, filename)): return _serve_file(request, filename, basepath) else: files_tried.append(os.path.join(basepath, filename)) if (settings.DEBUG or constants.PRIVATE in serve_docs) and privacy_level == constants.PRIVATE: # Handle private private_symlink = PrivateSymlink(project) basepath = private_symlink.project_root if os.path.exists(os.path.join(basepath, filename)): if not AdminPermission.is_member(user=request.user, obj=project): return _serve_401(request, project) return _serve_file(request, filename, basepath) else: files_tried.append(os.path.join(basepath, filename)) raise Http404('File not found. Tried these files: %s' % ','.join(files_tried))
def setUp(self): self.project = get(Project, slug='kong') self.translation = get(Project, slug='pip') self.translation.language = 'de' self.translation.main_language_project = self.project self.project.translations.add(self.translation) self.translation.save() self.project.save() self.symlink = PublicSymlink(self.project) get(Version, verbose_name='master', active=True, project=self.project) get(Version, verbose_name='master', active=True, project=self.translation) self.args = { 'project_root': self.symlink.project_root, 'translation_root': os.path.join(self.symlink.WEB_ROOT, self.translation.slug), } self.assertIn(self.translation, self.project.translations.all()) self.commands = []
def _serve_symlink_docs(request, project, privacy_level, filename=''): """Serve a file by symlink, or a 404 if not found.""" # Handle indexes if filename == '' or filename[-1] == '/': filename += 'index.html' # This breaks path joining, by ignoring the root when given an "absolute" path if filename[0] == '/': filename = filename[1:] log.info('Serving %s for %s', filename, project) files_tried = [] serve_docs = getattr(settings, 'SERVE_DOCS', [constants.PRIVATE]) if (settings.DEBUG or constants.PUBLIC in serve_docs) and privacy_level != constants.PRIVATE: # yapf: disable # noqa public_symlink = PublicSymlink(project) basepath = public_symlink.project_root if os.path.exists(os.path.join(basepath, filename)): return _serve_file(request, filename, basepath) files_tried.append(os.path.join(basepath, filename)) if (settings.DEBUG or constants.PRIVATE in serve_docs) and privacy_level == constants.PRIVATE: # yapf: disable # noqa # Handle private private_symlink = PrivateSymlink(project) basepath = private_symlink.project_root if os.path.exists(os.path.join(basepath, filename)): return _serve_file(request, filename, basepath) files_tried.append(os.path.join(basepath, filename)) raise Http404( 'File not found. Tried these files: {}'.format( ','.join(files_tried)), )
class TestPublicSymlinkVersions(BaseSymlinkVersions, TestCase): def setUp(self): self.project = get(Project, slug='kong') self.stable = get(Version, slug='stable', verbose_name='stable', active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = { 'project_root': self.symlink.project_root, 'latest_path': self.project.rtd_build_path('latest'), 'stable_path': self.project.rtd_build_path('stable'), } self.commands = [] @patched def test_no_symlink_private_versions(self): self.stable.privacy_level = 'private' self.stable.save() self.symlink.symlink_versions() commands = [ 'ln -nsf {latest_path} {project_root}/en/latest', ] for index, command in enumerate(commands): self.assertEqual(self.commands[index], command.format(**self.args)) def test_removed_versions(self): version_link = os.path.join(self.symlink.project_root, 'en', self.stable.slug) self.symlink.symlink_versions() self.assertTrue(os.path.lexists(version_link)) self.stable.privacy_level = 'private' self.stable.save() self.symlink.symlink_versions() self.assertTrue(not os.path.lexists(version_link))
class TestPublicSymlinkVersions(BaseSymlinkVersions, TestCase): def setUp(self): self.project = get(Project, slug='kong') self.stable = get( Version, slug='stable', verbose_name='stable', active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = { 'project_root': self.symlink.project_root, 'latest_path': self.project.rtd_build_path('latest'), 'stable_path': self.project.rtd_build_path('stable'), } self.commands = [] @patched def test_no_symlink_private_versions(self): self.stable.privacy_level = 'private' self.stable.save() self.symlink.symlink_versions() commands = [ 'ln -nsf {latest_path} {project_root}/en/latest', ] for index, command in enumerate(commands): self.assertEqual(self.commands[index], command.format(**self.args)) def test_removed_versions(self): version_link = os.path.join( self.symlink.project_root, 'en', self.stable.slug ) self.symlink.symlink_versions() self.assertTrue(os.path.lexists(version_link)) self.stable.privacy_level = 'private' self.stable.save() self.symlink.symlink_versions() self.assertTrue(not os.path.lexists(version_link))
def setUp(self): self.project = get(Project, slug="kong") self.version = get(Version, verbose_name="latest", active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = {"cname_root": self.symlink.CNAME_ROOT, "project_root": self.symlink.project_root} self.commands = []
class TestPublicSymlinkUnicode(TempSiterootCase, TestCase): def setUp(self): super(TestPublicSymlinkUnicode, self).setUp() self.project = get(Project, slug='kong', name=u'foo-∫', main_language_project=None) self.project.save() self.stable = get(Version, slug='foo-a', verbose_name=u'foo-∂', active=True, project=self.project) self.symlink = PublicSymlink(self.project) def test_symlink_no_error(self): try: self.symlink.run() except: self.fail('Symlink run raised an exception on unicode slug') def test_symlink_broadcast_calls_on_project_save(self): """ Test calls to ``readthedocs.core.utils.broadcast`` on Project.save(). When a Project is saved, we need to check that we are calling ``broadcast`` utility with the proper task and arguments to re-symlink them. """ with mock.patch('readthedocs.projects.models.broadcast') as broadcast: project = get(Project) # skipped on first save broadcast.assert_not_called() broadcast.reset_mock() project.description = 'New description' project.save() # called once for this project itself broadcast.assert_any_calls( type='app', task=symlink_project, args=[project.pk], ) broadcast.reset_mock() subproject = get(Project) # skipped on first save broadcast.assert_not_called() project.add_subproject(subproject) # subproject.save() is not called broadcast.assert_not_called() subproject.description = 'New subproject description' subproject.save() # subproject symlinks broadcast.assert_any_calls( type='app', task=symlink_project, args=[subproject.pk], ) # superproject symlinks broadcast.assert_any_calls( type='app', task=symlink_project, args=[project.pk], )
def setUp(self): self.project = get(Project, slug="kong") self.version = get(Version, verbose_name="latest", active=True, project=self.project) self.symlink = PublicSymlink(self.project) self.args = {"project_root": self.symlink.project_root, "doc_path": self.project.rtd_build_path()} self.commands = []