| 76 | | class APIDocResource(resource.Resource): |
|---|
| 77 | | """ |
|---|
| 78 | | """ |
|---|
| 79 | | def __init__(self, vhostPath, projectURLProto, projectRepoProto): |
|---|
| 80 | | self.vhostPath = vhostPath |
|---|
| 81 | | for name in ('projectURLProto', 'projectRepoProto'): |
|---|
| 82 | | string = locals()[name] |
|---|
| 83 | | if "%s" not in string: |
|---|
| 84 | | raise ValueError("Invalid string prototype '%s'" % string) |
|---|
| 85 | | setattr(self, name, string) |
|---|
| 86 | | |
|---|
| 87 | | def _executable(self, name): |
|---|
| 88 | | result = procutils.which(name)[0] |
|---|
| 89 | | if not result: |
|---|
| 90 | | raise ImportError("Can't locate %s executable" % name) |
|---|
| 91 | | |
|---|
| 92 | | def locateChild(self, request, segments): |
|---|
| 93 | | """ |
|---|
| 94 | | """ |
|---|
| 95 | | def ready(null): |
|---|
| 96 | | urlPath = "/api/%s/%s" % (projectName, apiFile) |
|---|
| 97 | | newURL = (request.scheme, request.host, urlPath, '', '', '') |
|---|
| 98 | | return resource.RedirectResource(*newURL), () |
|---|
| 99 | | |
|---|
| 100 | | projectName = segments[0] |
|---|
| 101 | | packageName = projectName.lower().replace("-", "_") |
|---|
| 102 | | if len(segments) > 1: |
|---|
| 103 | | apiFile = segments[1] |
|---|
| 104 | | else: |
|---|
| 105 | | apiFile = "%s.html" % packageName |
|---|
| 106 | | d = defer.maybeDeferred( |
|---|
| 107 | | self.ensureDocsPresent, projectName, packageName, apiFile) |
|---|
| 108 | | d.addCallback(ready) |
|---|
| 109 | | return d |
|---|
| 110 | | |
|---|
| 111 | | def ensureDocsPresent(self, projectName, packageName, apiFile): |
|---|
| 112 | | """ |
|---|
| 113 | | """ |
|---|
| 114 | | filePath = ospath.join(self.vhostPath, 'api', projectName, apiFile) |
|---|
| 115 | | if False and not ospath.exists(filePath): |
|---|
| 116 | | tmpDir = tempfile.mkdtemp() |
|---|
| 117 | | d = self.svn(tmpDir, projectName) |
|---|
| 118 | | d.addCallback(lambda _: self.pydoctor(tmpDir, projectName)) |
|---|
| 119 | | d.addCallback(lambda _: shutil.rmtree(tmpDir)) |
|---|
| 120 | | return d |
|---|
| 121 | | |
|---|
| 122 | | def svn(self, tmpDir, projectName): |
|---|
| 123 | | """ |
|---|
| 124 | | """ |
|---|
| 125 | | repo = self.projectRepoProto % projectName |
|---|
| 126 | | args = [ |
|---|
| 127 | | "export", "-q", "--force", |
|---|
| 128 | | "%s/%s/trunk" % (repo, projectName)] |
|---|
| 129 | | return util.getProcessValue( |
|---|
| 130 | | self._executable('svn'), args=args, path=tmpDir) |
|---|
| 131 | | |
|---|
| 132 | | def pydoctor(self, tmpDir, vhostPath, projectName): |
|---|
| 133 | | """ |
|---|
| 134 | | """ |
|---|
| 135 | | url = self.projectURLProto % projectName |
|---|
| 136 | | args = [ |
|---|
| 137 | | "--add-package=%s" % packageName, |
|---|
| 138 | | "--project-name=%s" % projectName, |
|---|
| 139 | | "--make-html", |
|---|
| 140 | | "--html-output=%s/api/%s" % (self.vhostPath, projectName), |
|---|
| 141 | | "--project-url=%s%s" % (url, projectName)] |
|---|
| 142 | | return util.getProcessValue( |
|---|
| 143 | | self._executable('pydoctor'), args=args, path=tmpDir) |
|---|
| 144 | | |
|---|
| 145 | | |
|---|