# -*- coding: utf-8 -*- from paver.easy import * from paver.setuputils import setup try: from paver.doctools import cog except: cog = None import fnmatch # patch to let it support list of patterns def new_fnmatch(self, pattern): if type(pattern) == list: for p in pattern: if fnmatch.fnmatch(self.name, p): return True return False else: return fnmatch.fnmatch(self.name, pattern) path.fnmatch = new_fnmatch import sys import re from subprocess import call, Popen PROJECT_DIR = path(__file__).dirname() sys.path.append(PROJECT_DIR) options = environment.options extradeps = [] if sys.version_info <= (2, 5): extradeps += 'simplejson' setup( name="pyload", version="0.5.0", description='Fast, lightweight and full featured download manager.', long_description=open(PROJECT_DIR / "README.md").read(), keywords=('pyload', 'download-manager', 'one-click-hoster', 'download'), url="http://pyload.org", download_url='http://pyload.org/download', license='AGPL v3', author="pyLoad Team", author_email="support@pyload.org", platforms=('Any',), #package_dir={'pyload': 'src'}, packages=['pyload'], #package_data=find_package_data(), #data_files=[], include_package_data=True, exclude_package_data={'pyload': ['docs*', 'scripts*', 'tests*']}, #exluced from build but not from sdist # 'bottle >= 0.10.0' not in list, because its small and contain little modifications install_requires=['pycurl', 'Beaker >= 1.6'] + extradeps, extras_require={ 'SSL': ["pyOpenSSL"], 'DLC': ['pycrypto'], 'Lightweight webserver': ['bjoern'], 'RSS plugins': ['feedparser'], 'Few Hoster plugins': ['BeautifulSoup>=3.2, <3.3'] }, #setup_requires=["setuptools_hg"], test_suite='nose.collector', tests_require=['nose', 'websocket-client >= 0.8.0', 'requests >= 1.2.2'], entry_points={ 'console_scripts': [ 'pyload = pyload.Core:main', 'pyload-cli = pyload.cli.Cli:main' ]}, zip_safe=False, classifiers=[ "Development Status :: 5 - Production/Stable", "Topic :: Internet :: WWW/HTTP", "Environment :: Console", "Environment :: Web Environment", "Intended Audience :: End Users/Desktop", "License :: OSI Approved :: GNU Affero General Public License v3", "Operating System :: OS Independent", "Programming Language :: Python :: 2" ] ) options( sphinx=Bunch( builddir="_build", sourcedir="" ), apitypes=Bunch( path="thrift", ), virtualenv=Bunch( dir="env", python="python2", virtual="virtualenv2", ), cog=Bunch( pattern=["*.py", "*.rst"], ) ) # xgettext args xargs = ["--from-code=utf-8", "--copyright-holder=pyLoad Team", "--package-name=pyLoad", "--package-version=%s" % options.version, "--msgid-bugs-address='bugs@pyload.org'"] @task @needs('cog') def html(): """Build html documentation""" module = path("docs") / "pyload" module.rmtree() call_task('paver.doctools.html') @task @needs('clean', 'generate_setup', 'webapp', 'setuptools.command.sdist') def sdist(): """ Build source code package with distutils """ @task @cmdopts([ ('path=', 'p', 'Thrift path'), ]) def apitypes(options): """ Generate data types stubs """ outdir = PROJECT_DIR / "pyload" / "remote" if (outdir / "gen-py").exists(): (outdir / "gen-py").rmtree() cmd = [options.apitypes.path, "-strict", "-o", outdir, "--gen", "py:slots,dynamic", outdir / "pyload.thrift"] print "running", cmd p = Popen(cmd) p.communicate() (outdir / "thriftgen").rmtree() (outdir / "gen-py").move(outdir / "thriftgen") #create light ttypes from pyload.remote.create_apitypes import main main() from pyload.remote.create_jstypes import main main() @task def webapp(): """ Builds the pyload web app. Nodejs and npm must be installed """ # TODO # npm install # bower install @task def generate_locale(): """ Generates localisation files """ # TODO restructure, many references are outdated EXCLUDE = ["BeautifulSoup.py", "module/gui", "module/cli", "web/locale", "web/ajax", "web/cnl", "web/pyload", "setup.py"] makepot("core", path("pyload"), EXCLUDE, "./pyLoadCore.py\n") makepot("cli", path("module") / "cli", [], includes="./pyLoadCli.py\n") makepot("setup", "", [], includes="./module/setup.py\n") EXCLUDE = ["ServerThread.py", "web/media/default"] # strings from js files strings = set() for fi in path("module/web").walkfiles(): if not fi.name.endswith(".js") and not fi.endswith(".coffee"): continue with open(fi, "rb") as c: content = c.read() strings.update(re.findall(r"_\s*\(\s*\"([^\"]+)", content)) strings.update(re.findall(r"_\s*\(\s*\'([^\']+)", content)) trans = path("module") / "web" / "translations.js" with open(trans, "wb") as js: for s in strings: js.write('_("%s")\n' % s) makepot("web", path("module/web"), EXCLUDE, "./%s\n" % trans.relpath(), [".py", ".html"], ["--language=Python"]) trans.remove() path("includes.txt").remove() print "Locale generated" @task def tests(): """ Run nosetests """ call(["tests/nosetests.sh"]) @task @cmdopts([ ('virtual=', 'v', 'virtualenv path'), ('python=', 'p', 'python path') ]) def virtualenv(options): """Setup virtual environment""" if path(options.dir).exists(): return call([options.virtual, "--no-site-packages", "--python", options.python, options.dir]) print "$ source %s/bin/activate" % options.dir @task def clean_env(): """Deletes the virtual environment""" env = path(options.virtualenv.dir) if env.exists(): env.rmtree() @task def clean(): """Cleans build directories""" path("build").rmtree() path("dist").rmtree() #helper functions def walk_trans(path, EXCLUDE, endings=[".py"]): result = "" for f in path.walkfiles(): if [True for x in EXCLUDE if x in f.dirname().relpath()]: continue if f.name in EXCLUDE: continue for e in endings: if f.name.endswith(e): result += "./%s\n" % f.relpath() break return result def makepot(domain, p, excludes=[], includes="", endings=[".py"], xxargs=[]): print "Generate %s.pot" % domain f = open("includes.txt", "wb") if includes: f.write(includes) if p: f.write(walk_trans(path(p), excludes, endings)) f.close() call(["xgettext", "--files-from=includes.txt", "--default-domain=%s" % domain] + xargs + xxargs) # replace charset und move file with open("%s.po" % domain, "rb") as f: content = f.read() path("%s.po" % domain).remove() content = content.replace("charset=CHARSET", "charset=UTF-8") with open("locale/%s.pot" % domain, "wb") as f: f.write(content) def change_owner(dir, uid, gid): for p in dir.walk(): p.chown(uid, gid) def change_mode(dir, mode, folder=False): for p in dir.walk(): if folder and p.isdir(): p.chmod(mode) elif p.isfile() and not folder: p.chmod(mode)