From b1c961b958e12ca35cba04a25c95823ea931e014 Mon Sep 17 00:00:00 2001 From: Pierre Tardy Date: Wed, 13 Aug 2014 19:53:37 +0200 Subject: [PATCH] rework www plugin pkg creation (again) With previous version, the plugins shared "static" directory inside site-package dir! We create one real module dir per plugin, so that we can use pkg_resource to store the built js. This way, we even have bdist_egg working and are ready for py2exe :) Signed-off-by: Pierre Tardy --- .../buildbot/www/plugin.py | 28 +++------ pkg/buildbot_pkg.py | 20 ++++-- pkg/test_buildbot_pkg.py | 61 ++++++++++++++----- www/.gitignore | 1 + www/MANIFEST.in | 2 - .../__init__.py} | 26 +------- www/codeparameter/MANIFEST.in | 2 - www/codeparameter/buildbot_codeparameter.py | 51 ---------------- .../buildbot_codeparameter/__init__.py} | 26 +------- www/codeparameter/guanlecoja/config.coffee | 4 +- www/codeparameter/setup.py | 2 +- .../buildbot_console_view/__init__.py | 19 ++++++ www/console_view/guanlecoja/config.coffee | 1 + www/console_view/setup.py | 2 +- www/guanlecoja/config.coffee | 2 +- www/setup.py | 2 +- .../buildbot_waterfall_view/__init__.py | 19 ++++++ www/waterfall_view/guanlecoja/config.coffee | 1 + www/waterfall_view/setup.py | 2 +- 19 files changed, 123 insertions(+), 148 deletions(-) rename www/console_view/buildbot_console_view.py => master/buildbot/www/plugin.py (57%) delete mode 100644 www/MANIFEST.in rename www/{buildbot_www.py => buildbot_www/__init__.py} (53%) delete mode 100644 www/codeparameter/MANIFEST.in delete mode 100644 www/codeparameter/buildbot_codeparameter.py rename www/{waterfall_view/buildbot_waterfall_view.py => codeparameter/buildbot_codeparameter/__init__.py} (53%) create mode 100644 www/console_view/buildbot_console_view/__init__.py create mode 100644 www/waterfall_view/buildbot_waterfall_view/__init__.py diff --git a/www/console_view/buildbot_console_view.py b/master/buildbot/www/plugin.py similarity index 57% rename from www/console_view/buildbot_console_view.py rename to master/buildbot/www/plugin.py index 633d3e70d75..ecffc4e95a0 100644 --- a/www/console_view/buildbot_console_view.py +++ b/master/buildbot/www/plugin.py @@ -13,29 +13,17 @@ # # Copyright Buildbot Team Members -import os +import pkg_resources from twisted.web import static - -def sibpath(*elts): - return os.path.join(os.path.dirname(__file__), *elts) - - class Application(object): - - def __init__(self): - self.description = "Buildbot UI" - # VERSION's location differs depending on whether we're installed - for f in sibpath('VERSION'), sibpath('static', 'VERSION'): - if os.path.exists(f): - self.version = open(f).read().strip() - break - else: - self.version = '' - self.static_dir = os.path.abspath(sibpath('static')) + def __init__(self, modulename, description): + self.description = description + self.version = pkg_resources.resource_string(modulename, "/VERSION").strip() + self.static_dir = pkg_resources.resource_filename(modulename, "/static") self.resource = static.File(self.static_dir) - -# create the interface for the setuptools entry point -ep = Application() + def __repr__(self): + return "www.plugin.Application(version={}, description={}, static_dir={})".format( + self.version, self.description, self.static_dir) diff --git a/pkg/buildbot_pkg.py b/pkg/buildbot_pkg.py index 0c1f458af0f..4a130a90d36 100644 --- a/pkg/buildbot_pkg.py +++ b/pkg/buildbot_pkg.py @@ -19,6 +19,7 @@ from distutils.version import LooseVersion from setuptools import setup from setuptools.command.egg_info import egg_info +from textwrap import dedent import os @@ -95,16 +96,26 @@ def build_js(cmd): global js_built if js_built: return + package = cmd.distribution.packages[0] if os.path.exists("gulpfile.js"): npm_version = check_output("npm -v") npm_bin = check_output("npm bin").strip() assert npm_version != "", "need nodejs and npm installed in current PATH" assert LooseVersion(npm_version) >= LooseVersion("1.4"), "npm < 1.4 (%s)" % (npm_version) cmd.spawn(['npm', 'install']) - cmd.spawn([os.path.join(npm_bin, "gulp"), 'prod']) - cmd.copy_tree('static', os.path.join("build", "lib", "static")) + cmd.spawn([os.path.join(npm_bin, "gulp"), 'default']) + with open(os.path.join("MANIFEST.in"), "w") as f: + f.write(dedent(""" + include %(package)s/VERSION + recursive-include %(package)s/static * + """ % dict(package=package))) - with open(os.path.join("build", "lib", "VERSION"), "w") as f: + cmd.copy_tree(os.path.join(package, 'static'), os.path.join("build", "lib", package, "static")) + + with open(os.path.join("build", "lib", package, "VERSION"), "w") as f: + f.write(cmd.distribution.metadata.version) + + with open(os.path.join(package, "VERSION"), "w") as f: f.write(cmd.distribution.metadata.version) js_built = True @@ -127,4 +138,5 @@ def run(self): def setup_www_plugin(**kw): - setup(version=getVersion("."), cmdclass=cmdclassforjs, **kw) + package = kw['packages'][0] + setup(version=getVersion(os.path.join(package, "__init__.py")), cmdclass=cmdclassforjs, **kw) diff --git a/pkg/test_buildbot_pkg.py b/pkg/test_buildbot_pkg.py index 5144957767c..3f82bf50f90 100644 --- a/pkg/test_buildbot_pkg.py +++ b/pkg/test_buildbot_pkg.py @@ -19,34 +19,46 @@ from subprocess import call from subprocess import check_call from twisted.trial import unittest +from textwrap import dedent +class BuildbotWWWPkg(unittest.TestCase): + pkgName = "buildbot_www" + pkgPaths = ["www"] + epName = "base" -class BuildbotPkg(unittest.TestCase): + loadTestScript = dedent(""" + import pkg_resources + apps = {} + for ep in pkg_resources.iter_entry_points('buildbot.www'): + apps[ep.name] = ep.load() + assert("scripts.js" in apps["%(epName)s"].resource.listNames()) + assert(apps["%(epName)s"].version.startswith("0.")) + assert(apps["%(epName)s"].description is not None) + print apps["%(epName)s"] + """) @property - def www(self): - return os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "www")) + def path(self): + return os.path.abspath(os.path.join(os.path.dirname(__file__), "..", *self.pkgPaths)) def rmtree(self, d): if os.path.isdir(d): shutil.rmtree(d) def setUp(self): - call("pip uninstall -y buildbot_www", shell=True) - self.rmtree(os.path.join(self.www, "build")) - self.rmtree(os.path.join(self.www, "dist")) - self.rmtree(os.path.join(self.www, "static")) + call("pip uninstall -y " + self.pkgName, shell=True) + self.rmtree(os.path.join(self.path, "build")) + self.rmtree(os.path.join(self.path, "dist")) + self.rmtree(os.path.join(self.path, "static")) def run_setup(self, cmd): - check_call("python setup.py " + cmd, shell=True, cwd=self.www) + check_call("python setup.py " + cmd, shell=True, cwd=self.path) def check_correct_installation(self): # assert we can import buildbot_www # and that it has an endpoint with resource containing file "script.js" check_call([ - 'python', '-c', - 'import buildbot_www;' # no comma - 'assert("scripts.js" in buildbot_www.ep.resource.listNames())']) + 'python', '-c', self.loadTestScript % dict(epName=self.epName)]) def test_install(self): self.run_setup("install") @@ -54,7 +66,13 @@ def test_install(self): def test_wheel(self): self.run_setup("bdist_wheel") - check_call("pip install dist/*.whl", shell=True, cwd=self.www) + check_call("pip install dist/*.whl", shell=True, cwd=self.path) + self.check_correct_installation() + + def test_egg(self): + self.run_setup("bdist_egg") + # egg installation is not supported by pip, so we use easy_install + check_call("easy_install dist/*.egg", shell=True, cwd=self.path) self.check_correct_installation() def test_develop(self): @@ -62,10 +80,25 @@ def test_develop(self): self.check_correct_installation() def test_develop_via_pip(self): - check_call("pip install -e .", shell=True, cwd=self.www) + check_call("pip install -e .", shell=True, cwd=self.path) self.check_correct_installation() def test_sdist(self): self.run_setup("sdist") - check_call("pip install dist/*.tar.gz", shell=True, cwd=self.www) + check_call("pip install dist/*.tar.gz", shell=True, cwd=self.path) self.check_correct_installation() + +class BuildbotConsolePkg(BuildbotWWWPkg): + pkgName = "buildbot-console-view" + pkgPaths = ["www", "console_view"] + epName = "console_view" + +class BuildbotWaterfallPkg(BuildbotWWWPkg): + pkgName = "buildbot-waterfall-view" + pkgPaths = ["www", "waterfall_view"] + epName = "waterfall_view" + +class BuildbotCodeparameterPkg(BuildbotWWWPkg): + pkgName = "buildbot-codeparameter" + pkgPaths = ["www", "codeparameter"] + epName = "codeparameter" diff --git a/www/.gitignore b/www/.gitignore index 9e6b9417817..f5834e864dd 100644 --- a/www/.gitignore +++ b/www/.gitignore @@ -1,3 +1,4 @@ +MANIFEST.in build !src/app/builders/build dist/ diff --git a/www/MANIFEST.in b/www/MANIFEST.in deleted file mode 100644 index 710e45d0dd3..00000000000 --- a/www/MANIFEST.in +++ /dev/null @@ -1,2 +0,0 @@ -include VERSION -recursive-include static * diff --git a/www/buildbot_www.py b/www/buildbot_www/__init__.py similarity index 53% rename from www/buildbot_www.py rename to www/buildbot_www/__init__.py index 633d3e70d75..72fc655932e 100644 --- a/www/buildbot_www.py +++ b/www/buildbot_www/__init__.py @@ -13,29 +13,7 @@ # # Copyright Buildbot Team Members -import os - -from twisted.web import static - - -def sibpath(*elts): - return os.path.join(os.path.dirname(__file__), *elts) - - -class Application(object): - - def __init__(self): - self.description = "Buildbot UI" - # VERSION's location differs depending on whether we're installed - for f in sibpath('VERSION'), sibpath('static', 'VERSION'): - if os.path.exists(f): - self.version = open(f).read().strip() - break - else: - self.version = '' - self.static_dir = os.path.abspath(sibpath('static')) - self.resource = static.File(self.static_dir) - +from buildbot.www.plugin import Application # create the interface for the setuptools entry point -ep = Application() +ep = Application(__name__, "Buildbot UI") diff --git a/www/codeparameter/MANIFEST.in b/www/codeparameter/MANIFEST.in deleted file mode 100644 index 710e45d0dd3..00000000000 --- a/www/codeparameter/MANIFEST.in +++ /dev/null @@ -1,2 +0,0 @@ -include VERSION -recursive-include static * diff --git a/www/codeparameter/buildbot_codeparameter.py b/www/codeparameter/buildbot_codeparameter.py deleted file mode 100644 index 4f3f2677f8b..00000000000 --- a/www/codeparameter/buildbot_codeparameter.py +++ /dev/null @@ -1,51 +0,0 @@ -# This file is part of Buildbot. Buildbot is free software: you can -# redistribute it and/or modify it under the terms of the GNU General Public -# License as published by the Free Software Foundation, version 2. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -# details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Copyright Buildbot Team Members - -import os - -from buildbot.schedulers.forcesched import TextParameter -from twisted.web import static - - -class CodeParameter(TextParameter): - - """A code editor using ace""" - spec_attributes = ["mode", "height"] - type = "code" - mode = "text" - height = 200 - - -def sibpath(*elts): - return os.path.join(os.path.dirname(__file__), *elts) - - -class Application(object): - - def __init__(self): - self.description = "Buildbot CodeParameter" - # VERSION's location differs depending on whether we're installed - for f in sibpath('VERSION'), sibpath('static', 'VERSION'): - if os.path.exists(f): - self.version = open(f).read().strip() - break - else: - self.version = '' - self.static_dir = os.path.abspath(sibpath('static')) - self.resource = static.File(self.static_dir) - - -# create the interface for the setuptools entry point -ep = Application() diff --git a/www/waterfall_view/buildbot_waterfall_view.py b/www/codeparameter/buildbot_codeparameter/__init__.py similarity index 53% rename from www/waterfall_view/buildbot_waterfall_view.py rename to www/codeparameter/buildbot_codeparameter/__init__.py index 633d3e70d75..2b3e1909949 100644 --- a/www/waterfall_view/buildbot_waterfall_view.py +++ b/www/codeparameter/buildbot_codeparameter/__init__.py @@ -13,29 +13,7 @@ # # Copyright Buildbot Team Members -import os - -from twisted.web import static - - -def sibpath(*elts): - return os.path.join(os.path.dirname(__file__), *elts) - - -class Application(object): - - def __init__(self): - self.description = "Buildbot UI" - # VERSION's location differs depending on whether we're installed - for f in sibpath('VERSION'), sibpath('static', 'VERSION'): - if os.path.exists(f): - self.version = open(f).read().strip() - break - else: - self.version = '' - self.static_dir = os.path.abspath(sibpath('static')) - self.resource = static.File(self.static_dir) - +from buildbot.www.plugin import Application # create the interface for the setuptools entry point -ep = Application() +ep = Application(__name__, "Buildbot forcescheduler parameter using ace.js to submit code") diff --git a/www/codeparameter/guanlecoja/config.coffee b/www/codeparameter/guanlecoja/config.coffee index 79ee6e91ccb..3ac5b48a617 100644 --- a/www/codeparameter/guanlecoja/config.coffee +++ b/www/codeparameter/guanlecoja/config.coffee @@ -17,14 +17,14 @@ module.exports = # Name of the plugin ### ########################################################################################### name: 'codeparameter' - plugin: true + ### ########################################################################################### # Directories ### ########################################################################################### dir: # The build folder is where the app resides once it's completely built - build: 'static' + build: 'buildbot_codeparameter/static' ### ########################################################################################### # Bower dependancies configuration diff --git a/www/codeparameter/setup.py b/www/codeparameter/setup.py index ee0153f5b9a..1ebaddbd706 100644 --- a/www/codeparameter/setup.py +++ b/www/codeparameter/setup.py @@ -29,7 +29,7 @@ author_email=u'tardyp@gmail.com', url='http://buildbot.net/', license='GNU GPL', - py_modules=['buildbot_www'], + packages=['buildbot_codeparameter'], entry_points=""" [buildbot.www] codeparameter = buildbot_codeparameter:ep diff --git a/www/console_view/buildbot_console_view/__init__.py b/www/console_view/buildbot_console_view/__init__.py new file mode 100644 index 00000000000..e48fc03c41c --- /dev/null +++ b/www/console_view/buildbot_console_view/__init__.py @@ -0,0 +1,19 @@ +# This file is part of Buildbot. Buildbot is free software: you can +# redistribute it and/or modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation, version 2. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright Buildbot Team Members + +from buildbot.www.plugin import Application + +# create the interface for the setuptools entry point +ep = Application(__name__, "Buildbot Console View UI") diff --git a/www/console_view/guanlecoja/config.coffee b/www/console_view/guanlecoja/config.coffee index 3aeb2eda66e..ddd4e9f783d 100644 --- a/www/console_view/guanlecoja/config.coffee +++ b/www/console_view/guanlecoja/config.coffee @@ -10,6 +10,7 @@ module.exports = # Name of the plugin ### ########################################################################################### name: 'console_view' + dir: build: 'buildbot_console_view/static' bower: testdeps: "guanlecoja-ui": diff --git a/www/console_view/setup.py b/www/console_view/setup.py index 01c53050386..3f00c2095cc 100644 --- a/www/console_view/setup.py +++ b/www/console_view/setup.py @@ -29,7 +29,7 @@ author_email=u'tardyp@gmail.com', url='http://buildbot.net/', license='GNU GPL', - py_modules=['buildbot_www'], + packages=['buildbot_console_view'], entry_points=""" [buildbot.www] console_view = buildbot_console_view:ep diff --git a/www/guanlecoja/config.coffee b/www/guanlecoja/config.coffee index 1297f6f8075..f130756e526 100644 --- a/www/guanlecoja/config.coffee +++ b/www/guanlecoja/config.coffee @@ -21,7 +21,7 @@ config = ### ########################################################################################### dir: # The build folder is where the app resides once it's completely built - build: 'static' + build: 'buildbot_www/static' ### ########################################################################################### # Bower dependancies configuration diff --git a/www/setup.py b/www/setup.py index 19a62ef5cd4..8ef3db60a80 100644 --- a/www/setup.py +++ b/www/setup.py @@ -29,7 +29,7 @@ author_email=u'tardyp@gmail.com', url='http://buildbot.net/', license='GNU GPL', - py_modules=['buildbot_www'], + packages=['buildbot_www'], entry_points=""" [buildbot.www] base = buildbot_www:ep diff --git a/www/waterfall_view/buildbot_waterfall_view/__init__.py b/www/waterfall_view/buildbot_waterfall_view/__init__.py new file mode 100644 index 00000000000..10f0bef1162 --- /dev/null +++ b/www/waterfall_view/buildbot_waterfall_view/__init__.py @@ -0,0 +1,19 @@ +# This file is part of Buildbot. Buildbot is free software: you can +# redistribute it and/or modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation, version 2. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., 51 +# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright Buildbot Team Members + +from buildbot.www.plugin import Application + +# create the interface for the setuptools entry point +ep = Application(__name__, "Buildbot Waterfall View UI") diff --git a/www/waterfall_view/guanlecoja/config.coffee b/www/waterfall_view/guanlecoja/config.coffee index 3c36800f735..9362ce9ca4a 100644 --- a/www/waterfall_view/guanlecoja/config.coffee +++ b/www/waterfall_view/guanlecoja/config.coffee @@ -10,6 +10,7 @@ module.exports = # Name of the plugin ### ########################################################################################### name: 'waterfall_view' + dir: build: 'buildbot_waterfall_view/static' bower: testdeps: "guanlecoja-ui": diff --git a/www/waterfall_view/setup.py b/www/waterfall_view/setup.py index 4efbb8590c7..228acddcfb4 100644 --- a/www/waterfall_view/setup.py +++ b/www/waterfall_view/setup.py @@ -30,7 +30,7 @@ author_email=u'tardyp@gmail.com', url='http://buildbot.net/', license='GNU GPL', - py_modules=['buildbot_www'], + packages=['buildbot_waterfall_view'], entry_points=""" [buildbot.www] waterfall_view = buildbot_waterfall_view:ep