forked from github.com/pypiserver
Rework standalone generation using ZIP.
+ Standalone executable based on wheel. + Properly use `pkg_resources` so reading `welcome-msg` file works even from within zip. + Mark `zip_safe=True` in setup.py. + Delete forgotten distutils startup script. + Build standalone before installing anything else, to check if any deps are missing. + Restore py25 in Travis.
This commit is contained in:
parent
542ffad6b0
commit
133afe28f7
@ -2,6 +2,7 @@ sudo: false
|
||||
language: python
|
||||
python: 2.7
|
||||
env:
|
||||
- TOX_ENV=py25
|
||||
- TOX_ENV=py26
|
||||
- TOX_ENV=py27
|
||||
- TOX_ENV=py32
|
||||
@ -9,12 +10,11 @@ env:
|
||||
- TOX_ENV=py34
|
||||
- TOX_ENV=pypy
|
||||
|
||||
install:
|
||||
- pip install tox
|
||||
|
||||
script:
|
||||
- tox -e $TOX_ENV
|
||||
- python -m pip install setuptools pip -U
|
||||
- ./bin/test_standalone.sh
|
||||
- pip install tox
|
||||
- tox -e $TOX_ENV
|
||||
|
||||
branches:
|
||||
except:
|
||||
|
@ -10,7 +10,7 @@ pypiserver - minimal PyPI server for use with pip/easy_install
|
||||
:Version: 1.1.9-dev.0
|
||||
:Date: 2015-03-8
|
||||
:Source: https://github.com/pypiserver/pypiserver
|
||||
:PyPI: https://pypi.python.org/pypi/pypiserver#downloads
|
||||
:PyPI: https://pypi.python.org/pypi/pypiserver
|
||||
:Travis: https://travis-ci.org/pypiserver/pypiserver
|
||||
:License: zlib/libpng + MIT
|
||||
|
||||
@ -308,7 +308,7 @@ Running ``pypi-server -h`` will print a detailed usage message::
|
||||
-u
|
||||
allow updating to unstable version (alpha, beta, rc, dev versions)
|
||||
|
||||
Visit https://pypi.python.org/pypi/pypiserver for more information.
|
||||
Visit https://github.com/pypiserver/pypiserver for more information.
|
||||
|
||||
|
||||
|
||||
@ -448,11 +448,6 @@ unstable packages on different paths::
|
||||
|
||||
Sources
|
||||
=======
|
||||
Python-packages with source releases can be downloaded from
|
||||
https://pypi.python.org/pypi/pypiserver
|
||||
|
||||
The in-development sources are hosted at https://github.com/pypiserver/pypiserver.
|
||||
|
||||
Use::
|
||||
|
||||
git clone https://github.com/pypiserver/pypiserver.git
|
||||
|
@ -1,7 +1,7 @@
|
||||
#! /bin/sh
|
||||
|
||||
## Requires this script in your PATH:
|
||||
## https://github.com/git/git/blob/master/contrib/workdir/git-new-workdir
|
||||
##
|
||||
## Create an executable file and add it into `standalone` branch
|
||||
##
|
||||
## Invoke it with any arg to avoid committing into `standalone` branch.
|
||||
|
||||
my_dir="$(dirname "$0")"
|
||||
@ -18,13 +18,12 @@ fi
|
||||
gitversion=$(git describe --tags)
|
||||
rm -rf .standalone
|
||||
if nwd_dump=$( "$git_wdir" . .standalone standalone 2>&1 ); then
|
||||
./bin/gen-standalone.py
|
||||
chmod a+xr ./pypi-server-standalone.py
|
||||
./bin/gen-standalone.sh
|
||||
cp -p pypi-server-standalone.py .standalone
|
||||
cd .standalone
|
||||
if [ $# -lt 1 ]; then
|
||||
git add .
|
||||
git commit -m "add pypi-server-standalone $gitversion"
|
||||
git commit -m "Add pypi-server-standalone $gitversion"
|
||||
fi
|
||||
else
|
||||
echo "git-new-workdir: failed due to: $nwd_dump"
|
||||
|
@ -1,66 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""generate a single file pypi-server script"""
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os, zlib, base64, itertools
|
||||
try:
|
||||
import cPickle
|
||||
except ImportError:
|
||||
import pickle as cPickle
|
||||
|
||||
def find_files(path):
|
||||
for dirpath, dirnames, filenames in os.walk(path):
|
||||
for f in filenames:
|
||||
yield os.path.join(dirpath, f)
|
||||
|
||||
def myExecFile(file, g, l):
|
||||
try:
|
||||
execfile(file, g, l)
|
||||
except NameError:
|
||||
with open(file) as fd:
|
||||
txt = fd.read()
|
||||
exec(txt, g, l)
|
||||
|
||||
def get_version():
|
||||
d = {}
|
||||
try:
|
||||
myExecFile("pypiserver/__init__.py", d, d)
|
||||
except (ImportError, RuntimeError):
|
||||
pass
|
||||
return d["__version__"]
|
||||
|
||||
|
||||
def main():
|
||||
name2src = {}
|
||||
|
||||
for f in itertools.chain(find_files("pypiserver"),
|
||||
find_files("vendor")):
|
||||
if not f.endswith(".py"):
|
||||
continue
|
||||
|
||||
k = f.replace('/', '.')[:-3]
|
||||
if k.startswith("vendor."):
|
||||
k = k[len("vendor."):]
|
||||
name2src[k] = open(f).read()
|
||||
|
||||
data = cPickle.dumps(name2src, 2)
|
||||
data = zlib.compress(data, 9)
|
||||
data = base64.encodestring(data)
|
||||
|
||||
try:
|
||||
data = str(data, encoding='ascii')
|
||||
except TypeError: # we were in PY2
|
||||
data = '%s' % data
|
||||
|
||||
script = open("pypi-server-in.py").read()
|
||||
script = script.replace("@VERSION@", get_version())
|
||||
script = script.replace('@SOURCES@', data)
|
||||
dst = "pypi-server-standalone.py"
|
||||
open(dst, "wt").write(script)
|
||||
os.chmod(dst, 755)
|
||||
print("created %s"%dst)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
36
bin/gen-standalone.sh
Executable file
36
bin/gen-standalone.sh
Executable file
@ -0,0 +1,36 @@
|
||||
#! /bin/sh
|
||||
##
|
||||
## Create an executable zip file.
|
||||
|
||||
exec_zip="./pypi-server-standalone.py"
|
||||
|
||||
my_dir="$(dirname "$0")"
|
||||
cd $my_dir/..
|
||||
|
||||
rm -rf ./build/* ./dist/*
|
||||
python setup.py bdist_wheel
|
||||
wheel="./dist/pypiserver-*.whl"
|
||||
|
||||
|
||||
## Modify `wheel` archive with `__main__.py` at root,
|
||||
# prepend it with a python-flashbang, and
|
||||
# add header-comments >= 10-lines so that
|
||||
# ``head pypiserver*.py`` behaves politely.
|
||||
#
|
||||
gitversion=$(git describe --tags)
|
||||
unzip -jo $wheel pypiserver/__main__.py -d ./dist
|
||||
zip -d $wheel pypiserver/__main__.py
|
||||
zip -mj $wheel ./dist/__main__.py
|
||||
cat - $wheel > "$exec_zip" << EOF
|
||||
#!/usr/bin/env python
|
||||
##
|
||||
## Standalone pypiserver-$gitversion
|
||||
##
|
||||
## Execute it like that:
|
||||
## $exec_zip <packages_dir>
|
||||
## To get more help, type:
|
||||
## $exec_zip --help
|
||||
##
|
||||
## BINARY CONTENT FOLLOWS
|
||||
EOF
|
||||
chmod a+xr "$exec_zip"
|
@ -1,4 +1,6 @@
|
||||
#! /bin/sh
|
||||
## Test standalone generation & execution.
|
||||
##
|
||||
|
||||
my_dir="$(dirname "$0")"
|
||||
cd $my_dir/..
|
||||
@ -11,4 +13,4 @@ git branch --track standalone origin/standalone
|
||||
server_pid=$!
|
||||
sleep 2
|
||||
|
||||
kill $server_pid # Killing fails if server failed starting-up.
|
||||
kill $server_pid && echo "Server killed nicely." # Kill fails if server failed.
|
||||
|
@ -1,5 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
## Failback script if installed with `distutils`.
|
||||
if __name__ == "__main__":
|
||||
from pypiserver.core import main
|
||||
main()
|
@ -1,66 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
"""standalone pypi-server, version @VERSION@"""
|
||||
|
||||
sources = """
|
||||
@SOURCES@"""
|
||||
|
||||
import sys, base64, zlib
|
||||
|
||||
|
||||
class DictImporter(object):
|
||||
sources = None
|
||||
|
||||
def find_module(self, fullname, path=None):
|
||||
if fullname in self.sources:
|
||||
return self
|
||||
if fullname + '.__init__' in self.sources:
|
||||
return self
|
||||
return None
|
||||
|
||||
def load_module(self, fullname):
|
||||
try:
|
||||
s = self.sources[fullname]
|
||||
is_pkg = False
|
||||
except KeyError:
|
||||
s = self.sources[fullname + '.__init__']
|
||||
is_pkg = True
|
||||
|
||||
co = compile(s, fullname, 'exec')
|
||||
try:
|
||||
module = sys.modules.setdefault(fullname, type(sys)(fullname))
|
||||
except TypeError: # jython?
|
||||
import types
|
||||
module = sys.modules.setdefault(fullname, types.ModuleType(fullname))
|
||||
module.__file__ = __file__
|
||||
module.__loader__ = self
|
||||
if is_pkg:
|
||||
module.__path__ = [fullname]
|
||||
|
||||
do_exec(co, module.__dict__)
|
||||
return sys.modules[fullname]
|
||||
|
||||
def get_source(self, name):
|
||||
res = self.sources.get(name)
|
||||
if res is None:
|
||||
res = self.sources.get(name + '.__init__')
|
||||
return res
|
||||
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
import pickle
|
||||
exec("def do_exec(co, loc): exec(co, loc)\n")
|
||||
sources = sources.encode("ascii") # ensure bytes
|
||||
d = zlib.decompress(base64.decodebytes(sources))
|
||||
sources = pickle.loads(zlib.decompress(base64.decodebytes(sources)), encoding="utf-8")
|
||||
else:
|
||||
import cPickle as pickle
|
||||
exec("def do_exec(co, loc): exec co in loc\n")
|
||||
sources = pickle.loads(zlib.decompress(base64.decodestring(sources)))
|
||||
|
||||
importer = DictImporter()
|
||||
importer.sources = sources
|
||||
sys.meta_path.append(importer)
|
||||
|
||||
if __name__ == "__main__":
|
||||
from pypiserver import __main__
|
||||
__main__.main()
|
@ -21,7 +21,7 @@ def init_logging(level=None, frmt=None, filename=None):
|
||||
|
||||
|
||||
def usage():
|
||||
sys.stdout.write("""pypi-server [OPTIONS] [PACKAGES_DIRECTORY...]
|
||||
return """pypi-server [OPTIONS] [PACKAGES_DIRECTORY...]
|
||||
start PyPI compatible package server serving packages from
|
||||
PACKAGES_DIRECTORY. If PACKAGES_DIRECTORY is not given on the
|
||||
command line, it uses the default ~/packages. pypiserver scans this
|
||||
@ -130,7 +130,7 @@ The following additional options can be specified with -U:
|
||||
allow updating to unstable version (alpha, beta, rc, dev versions)
|
||||
|
||||
Visit https://pypi.python.org/pypi/pypiserver for more information.
|
||||
""")
|
||||
"""
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
@ -241,7 +241,7 @@ def main(argv=None):
|
||||
elif k == "-v":
|
||||
verbosity += 1
|
||||
elif k in ("-h", "--help"):
|
||||
usage()
|
||||
print(usage())
|
||||
sys.exit(0)
|
||||
|
||||
if password_file and password_file != '.' and not authenticated:
|
||||
|
@ -126,37 +126,16 @@ def configure(root=None,
|
||||
#
|
||||
try:
|
||||
if not welcome_file:
|
||||
welcome_file = pkg_resources.resource_filename( # @UndefinedVariable
|
||||
__name__, "welcome.html") # @UndefinedVariable
|
||||
config.welcome_file = "welcome.html"
|
||||
config.welcome_msg = pkg_resources.resource_string( # @UndefinedVariable
|
||||
__name__, "welcome.html").decode("utf-8") # @UndefinedVariable
|
||||
else:
|
||||
config.welcome_file = welcome_file
|
||||
with io.open(config.welcome_file, 'r', encoding='utf-8') as fd:
|
||||
with io.open(welcome_file, 'r', encoding='utf-8') as fd:
|
||||
config.welcome_msg = fd.read()
|
||||
except Exception:
|
||||
log.warning(
|
||||
"Could not load welcome-file(%s)!", welcome_file, exc_info=1)
|
||||
if not config.welcome_msg:
|
||||
from textwrap import dedent
|
||||
config.welcome_msg = dedent("""\
|
||||
<html><head><title>Welcome to pypiserver!</title></head><body>
|
||||
<h1>Welcome to pypiserver!</h1>
|
||||
<p>This is a PyPI compatible package index serving {{NUMPKGS}} packages.</p>
|
||||
|
||||
<p> To use this server with pip, run the the following command:
|
||||
<blockquote><pre>
|
||||
pip install -i {{URL}}simple/ PACKAGE [PACKAGE2...]
|
||||
</pre></blockquote></p>
|
||||
|
||||
<p> To use this server with easy_install, run the the following command:
|
||||
<blockquote><pre>
|
||||
easy_install -i {{URL}}simple/ PACKAGE
|
||||
</pre></blockquote></p>
|
||||
|
||||
<p>The complete list of all packages can be found <a href="{{PACKAGES}}">here</a> or via the <a href="{{SIMPLE}}">simple</a> index.</p>
|
||||
|
||||
<p>This instance is running version {{VERSION}} of the <a href="http://pypi.python.org/pypi/pypiserver">pypiserver</a> software.</p>
|
||||
</body></html>\
|
||||
""")
|
||||
|
||||
config.log_req_frmt = log_req_frmt
|
||||
config.log_res_frmt = log_res_frmt
|
||||
config.log_err_frmt = log_err_frmt
|
||||
|
6
setup.py
6
setup.py
@ -48,18 +48,16 @@ setup(name="pypiserver",
|
||||
"Operating System :: POSIX",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python :: 2",
|
||||
"Programming Language :: Python :: 2.5",
|
||||
"Programming Language :: Python :: 2.6",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.0",
|
||||
"Programming Language :: Python :: 3.1",
|
||||
"Programming Language :: Python :: 3.2",
|
||||
"Programming Language :: Python :: 3.3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
"Topic :: Software Development :: Build Tools",
|
||||
"Topic :: System :: Software Distribution"],
|
||||
zip_safe=False,
|
||||
zip_safe=True,
|
||||
entry_points={
|
||||
'paste.app_factory': ['main=pypiserver:paste_app_factory'],
|
||||
'console_scripts': ['pypi-server=pypiserver.__main__:main']
|
||||
|
@ -1,11 +1,11 @@
|
||||
#! /usr/bin/env py.test
|
||||
|
||||
from pypiserver import __main__, bottle # do no remove. needed for bottle
|
||||
from pypiserver import __main__, bottle
|
||||
import pytest, webtest
|
||||
import logging
|
||||
|
||||
## Enable logging to detect any problems with it
|
||||
##
|
||||
import logging
|
||||
__main__.init_logging(level=logging.NOTSET)
|
||||
|
||||
@pytest.fixture()
|
||||
|
@ -1,11 +1,11 @@
|
||||
#! /usr/bin/env py.test
|
||||
|
||||
import pytest
|
||||
from pypiserver import core, __main__
|
||||
from pypiserver import __main__, core
|
||||
import logging
|
||||
|
||||
## Enable logging to detect any problems with it
|
||||
##
|
||||
import logging
|
||||
__main__.init_logging(level=logging.NOTSET)
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#! /usr/bin/env py.test
|
||||
|
||||
import sys, os, pytest, logging
|
||||
from pypiserver import core, __main__
|
||||
from pypiserver import __main__, core
|
||||
try:
|
||||
from unittest import mock
|
||||
except ImportError:
|
||||
|
1
vendor
1
vendor
@ -1 +0,0 @@
|
||||
Subproject commit f1b8d33f3ee3279ac4d8a27c921ebd3a122ec594
|
Loading…
Reference in New Issue
Block a user