Commit bee78e98 authored by tarek's avatar tarek

merge dance

--HG--
branch : distribute
extra : rebase_source : 35e424deb7b3bef880c53fa50dbe079f18076e67
parents 5109e586 dcc66e81
......@@ -6,8 +6,10 @@ CHANGES
0.6.4
-----
* Added the generation of distribute_setup_3k.py during the release.
* Added the generation of `distribute_setup_3k.py` during the release.
* Added an upload_docs command to easily upload project documentation to
PyPI's http://packages.python.org.
-----
0.6.3
......
......@@ -4,6 +4,7 @@ Contributors
* Alex Grönholm
* Hanno Schlichting
* Jannis Leidel
* Lennart Regebro
* Martin von Loewis
* Philip Envey
......
......@@ -80,14 +80,14 @@ distribute_setup.py
Download ``distribute_setup.py`` and execute it, using the Python interpreter of
your choice.
If your shell has the ``wget`` program you can do::
If your shell has the ``curl`` program you can do::
$ wget http://nightly.ziade.org/distribute_setup.py
$ curl -O http://nightly.ziade.org/distribute_setup.py
$ python distribute_setup.py
If you are under Python 3, use ``distribute_setup_3k.py``::
$ wget http://nightly.ziade.org/distribute_setup_3k.py
$ curl -O http://nightly.ziade.org/distribute_setup_3k.py
$ python distribute_setup_3k.py
Notice that both files are provided in the source release.
......@@ -105,7 +105,7 @@ Source installation
Download the source tarball, uncompress it, then run the install command::
$ wget http://pypi.python.org/packages/source/d/distribute/distribute-0.6.4.tar.gz
$ curl -O http://pypi.python.org/packages/source/d/distribute/distribute-0.6.4.tar.gz
$ tar -xzvf distribute-0.6.4.tar.gz
$ cd distribute-0.6
$ python setup.py install
......
......@@ -7,6 +7,7 @@ build_py = setuptools.command.build_py:build_py
saveopts = setuptools.command.saveopts:saveopts
egg_info = setuptools.command.egg_info:egg_info
register = setuptools.command.register:register
upload_docs = setuptools.command.upload_docs:upload_docs
install_egg_info = setuptools.command.install_egg_info:install_egg_info
alias = setuptools.command.alias:alias
easy_install = setuptools.command.easy_install:easy_install
......
/**
* Sphinx stylesheet -- default theme
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: Arial, sans-serif;
font-size: 100%;
background-color: #111;
color: #555;
margin: 0;
padding: 0;
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 300px;
}
hr{
border: 1px solid #B1B4B6;
}
div.document {
background-color: #eee;
}
div.body {
background-color: #ffffff;
color: #3E4349;
padding: 0 30px 30px 30px;
font-size: 0.8em;
}
div.footer {
color: #555;
width: 100%;
padding: 13px 0;
text-align: center;
font-size: 75%;
}
div.footer a {
color: #444;
text-decoration: underline;
}
div.related {
background-color: #6BA81E;
line-height: 32px;
color: #fff;
text-shadow: 0px 1px 0 #444;
font-size: 0.80em;
}
div.related a {
color: #E2F3CC;
}
div.sphinxsidebar {
font-size: 0.75em;
line-height: 1.5em;
width: 300px
}
div.sphinxsidebarwrapper{
padding: 20px 0;
}
div.sphinxsidebar h3,
div.sphinxsidebar h4 {
font-family: Arial, sans-serif;
color: #222;
font-size: 1.2em;
font-weight: normal;
margin: 0;
padding: 5px 10px;
background-color: #ddd;
text-shadow: 1px 1px 0 white
}
div.sphinxsidebar h4{
font-size: 1.1em;
}
div.sphinxsidebar h3 a {
color: #444;
}
div.sphinxsidebar p {
color: #888;
padding: 5px 20px;
}
div.sphinxsidebar p.topless {
}
div.sphinxsidebar ul {
margin: 10px 10px 10px 20px;
padding: 0;
color: #000;
}
div.sphinxsidebar a {
color: #444;
}
div.sphinxsidebar input {
border: 1px solid #ccc;
font-family: sans-serif;
font-size: 1em;
}
div.sphinxsidebar input[type=text]{
margin-left: 20px;
}
/* -- body styles ----------------------------------------------------------- */
a {
color: #005B81;
text-decoration: none;
}
a:hover {
color: #E32E00;
text-decoration: underline;
}
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: Arial, sans-serif;
background-color: #BED4EB;
font-weight: normal;
color: #212224;
margin: 30px 0px 10px 0px;
padding: 5px 0 5px 10px;
text-shadow: 0px 1px 0 white
}
div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
div.body h2 { font-size: 150%; background-color: #C8D5E3; }
div.body h3 { font-size: 120%; background-color: #D8DEE3; }
div.body h4 { font-size: 110%; background-color: #D8DEE3; }
div.body h5 { font-size: 100%; background-color: #D8DEE3; }
div.body h6 { font-size: 100%; background-color: #D8DEE3; }
a.headerlink {
color: #c60f0f;
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
}
a.headerlink:hover {
background-color: #c60f0f;
color: white;
}
div.body p, div.body dd, div.body li {
line-height: 1.5em;
}
div.admonition p.admonition-title + p {
display: inline;
}
div.highlight{
background-color: white;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;
}
div.seealso {
background-color: #ffc;
border: 1px solid #ff6;
}
div.topic {
background-color: #eee;
}
div.warning {
background-color: #ffe4e4;
border: 1px solid #f66;
}
p.admonition-title {
display: inline;
}
p.admonition-title:after {
content: ":";
}
pre {
padding: 10px;
background-color: White;
color: #222;
line-height: 1.2em;
border: 1px solid #C6C9CB;
font-size: 1.2em;
margin: 1.5em 0 1.5em 0;
-webkit-box-shadow: 1px 1px 1px #d8d8d8;
-moz-box-shadow: 1px 1px 1px #d8d8d8;
}
tt {
background-color: #ecf0f3;
color: #222;
padding: 1px 2px;
font-size: 1.2em;
font-family: monospace;
}
.c { color: #999988; font-style: italic } /* Comment */
.k { font-weight: bold } /* Keyword */
.o { font-weight: bold } /* Operator */
.cm { color: #999988; font-style: italic } /* Comment.Multiline */
.cp { color: #999999; font-weight: bold } /* Comment.preproc */
.c1 { color: #999988; font-style: italic } /* Comment.Single */
.gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.ge { font-style: italic } /* Generic.Emph */
.gr { color: #aa0000 } /* Generic.Error */
.gh { color: #999999 } /* Generic.Heading */
.gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.go { color: #111 } /* Generic.Output */
.gp { color: #555555 } /* Generic.Prompt */
.gs { font-weight: bold } /* Generic.Strong */
.gu { color: #aaaaaa } /* Generic.Subheading */
.gt { color: #aa0000 } /* Generic.Traceback */
.kc { font-weight: bold } /* Keyword.Constant */
.kd { font-weight: bold } /* Keyword.Declaration */
.kp { font-weight: bold } /* Keyword.Pseudo */
.kr { font-weight: bold } /* Keyword.Reserved */
.kt { color: #445588; font-weight: bold } /* Keyword.Type */
.m { color: #009999 } /* Literal.Number */
.s { color: #bb8844 } /* Literal.String */
.na { color: #008080 } /* Name.Attribute */
.nb { color: #999999 } /* Name.Builtin */
.nc { color: #445588; font-weight: bold } /* Name.Class */
.no { color: #ff99ff } /* Name.Constant */
.ni { color: #800080 } /* Name.Entity */
.ne { color: #990000; font-weight: bold } /* Name.Exception */
.nf { color: #990000; font-weight: bold } /* Name.Function */
.nn { color: #555555 } /* Name.Namespace */
.nt { color: #000080 } /* Name.Tag */
.nv { color: purple } /* Name.Variable */
.ow { font-weight: bold } /* Operator.Word */
.mf { color: #009999 } /* Literal.Number.Float */
.mh { color: #009999 } /* Literal.Number.Hex */
.mi { color: #009999 } /* Literal.Number.Integer */
.mo { color: #009999 } /* Literal.Number.Oct */
.sb { color: #bb8844 } /* Literal.String.Backtick */
.sc { color: #bb8844 } /* Literal.String.Char */
.sd { color: #bb8844 } /* Literal.String.Doc */
.s2 { color: #bb8844 } /* Literal.String.Double */
.se { color: #bb8844 } /* Literal.String.Escape */
.sh { color: #bb8844 } /* Literal.String.Heredoc */
.si { color: #bb8844 } /* Literal.String.Interpol */
.sx { color: #bb8844 } /* Literal.String.Other */
.sr { color: #808000 } /* Literal.String.Regex */
.s1 { color: #bb8844 } /* Literal.String.Single */
.ss { color: #bb8844 } /* Literal.String.Symbol */
.bp { color: #999999 } /* Name.Builtin.Pseudo */
.vc { color: #ff99ff } /* Name.Variable.Class */
.vg { color: #ff99ff } /* Name.Variable.Global */
.vi { color: #ff99ff } /* Name.Variable.Instance */
.il { color: #009999 } /* Literal.Number.Integer.Long */
\ No newline at end of file
[theme]
inherit = basic
stylesheet = nature.css
pygments_style = tango
......@@ -16,20 +16,19 @@
import sys, os
# If your extensions are in another directory, add it here. If the directory
# is relative to the documentation root, use os.path.abspath to make it
# absolute, like shown here.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.append(os.path.abspath('.'))
# General configuration
# ---------------------
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = []
# Add any paths that contain templates here, relative to this directory.
templates_path = ['.templates']
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.txt'
......@@ -49,9 +48,9 @@ copyright = u'2009, The fellowship of the packaging'
# built documents.
#
# The short X.Y version.
version = '0.6.1'
version = '0.6.4'
# The full version, including alpha/beta/rc tags.
release = '0.6.1'
release = '0.6.4'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
......@@ -87,21 +86,30 @@ exclude_trees = []
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# Options for HTML output
# -----------------------
# The style sheet to use for HTML and HTML Help pages. A file of that name
# must exist either in Sphinx' static/ path, or in one of the custom paths
# given in html_static_path.
html_style = 'default.css'
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
html_theme = 'nature'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
html_theme_path = ['_theme']
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
html_title = "Distribute documentation"
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
html_short_title = "Distribute"
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
......@@ -115,7 +123,7 @@ html_style = 'default.css'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['.static']
#html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
......@@ -141,8 +149,8 @@ html_static_path = ['.static']
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, the reST sources are included in the HTML build as _sources/<name>.
#html_copy_source = True
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
......@@ -156,8 +164,7 @@ html_static_path = ['.static']
htmlhelp_basename = 'Distributedoc'
# Options for LaTeX output
# ------------------------
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
......@@ -166,7 +173,7 @@ htmlhelp_basename = 'Distributedoc'
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, document class [howto/manual]).
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'Distribute.tex', ur'Distribute Documentation',
ur'The fellowship of the packaging', 'manual'),
......
......@@ -330,7 +330,9 @@ to restrict downloading to hosts in your own intranet. See the section below
on `Command-Line Options`_ for more details on the ``--allow-hosts`` option.
By default, there are no host restrictions in effect, but you can change this
default by editing the appropriate `configuration files`_ and adding::
default by editing the appropriate `configuration files`_ and adding:
.. code-block:: ini
[easy_install]
allow_hosts = *.myintranet.example.com,*.python.org
......@@ -411,7 +413,9 @@ generated directory listing (such as the Apache web server provides).
If you are setting up an intranet site for package downloads, you may want to
configure the target machines to use your download site by default, adding
something like this to their `configuration files`_::
something like this to their `configuration files`_:
.. code-block:: ini
[easy_install]
find_links = http://mypackages.example.com/somedir/
......@@ -445,7 +449,9 @@ Controlling Build Options
EasyInstall respects standard distutils `Configuration Files`_, so you can use
them to configure build options for packages that it installs from source. For
example, if you are on Windows using the MinGW compiler, you can configure the
default compiler by putting something like this::
default compiler by putting something like this:
.. code-block:: ini
[build]
compiler = mingw32
......@@ -593,7 +599,9 @@ distutils configuration files, under the command heading ``easy_install``.
EasyInstall will look first for a ``setup.cfg`` file in the current directory,
then a ``~/.pydistutils.cfg`` or ``$HOME\\pydistutils.cfg`` (on Unix-like OSes
and Windows, respectively), and finally a ``distutils.cfg`` file in the
``distutils`` package directory. Here's a simple example::
``distutils`` package directory. Here's a simple example:
.. code-block:: ini
[easy_install]
......@@ -986,7 +994,9 @@ The next step is to create or modify ``distutils.cfg`` in the ``distutils``
directory of your Python library. The correct directory will be something like
``/usr/lib/python2.X/distutils`` on most Posix systems and something like
``C:\\Python2X\Lib\distutils`` on Windows machines. Add the following lines
to the file, substituting the correct Python version if necessary::
to the file, substituting the correct Python version if necessary:
.. code-block:: ini
[install]
install_lib = ~/lib/python2.3
......@@ -1031,7 +1041,9 @@ location, because it is already configured to process ``.pth`` files, and
EasyInstall already knows this.
Before installing EasyInstall/setuptools, just create a ``~/.pydistutils.cfg``
file with the following contents (or add this to the existing contents)::
file with the following contents (or add this to the existing contents):
.. code-block:: ini
[install]
install_lib = ~/Library/Python/$py_version_short/site-packages
......@@ -1105,7 +1117,9 @@ Assuming that you want to install packages in a directory called ``~/py-lib``,
and scripts in ``~/bin``, here's what you need to do:
First, edit ``~/.pydistutils.cfg`` to include these settings, if you don't
already have them::
already have them:
.. code-block:: ini
[install]
install_lib = ~/py-lib
......
......@@ -36,20 +36,21 @@ to a list of names of packages containing fixers.
A typical setup.py can look something like this::
from setuptools import setup
setup(name='your.module',
version = '1.0',
description='This is your awesome module',
author='You',
author_email='your@email',
package_dir = {'': 'src'},
packages = ['your', 'you.module'],
test_suite = 'your.module.tests',
use_2to3 = True,
convert_2to3_doctests = ['src/your/module/README.txt'],
use_2to3_fixers = ['your.fixers']
)
from setuptools import setup
setup(
name='your.module',
version = '1.0',
description='This is your awesome module',
author='You',
author_email='your@email',
package_dir = {'': 'src'},
packages = ['your', 'you.module'],
test_suite = 'your.module.tests',
use_2to3 = True,
convert_2to3_doctests = ['src/your/module/README.txt'],
use_2to3_fixers = ['your.fixers']
)
Differential conversion
-----------------------
......@@ -96,25 +97,26 @@ install process will continue as normal, but if you want to get rid of that
error this is easy. Simply conditionally add the new parameters into an extra
dict and pass that dict into setup()::
from setuptools import setup
import sys
extra = {}
if sys.version_info >= (3,):
extra['use_2to3'] = True
extra['convert_2to3_doctests'] = ['src/your/module/README.txt']
extra['use_2to3_fixers'] = ['your.fixers']
setup(name='your.module',
version = '1.0',
description='This is your awesome module',
author='You',
author_email='your@email',
package_dir = {'': 'src'},
packages = ['your', 'you.module'],
test_suite = 'your.module.tests',
**extra
)
from setuptools import setup
import sys
extra = {}
if sys.version_info >= (3,):
extra['use_2to3'] = True
extra['convert_2to3_doctests'] = ['src/your/module/README.txt']
extra['use_2to3_fixers'] = ['your.fixers']
setup(
name='your.module',
version = '1.0',
description='This is your awesome module',
author='You',
author_email='your@email',
package_dir = {'': 'src'},
packages = ['your', 'you.module'],
test_suite = 'your.module.tests',
**extra
)
This way the parameters will only be used under Python 3, where you have to
use Distribute.
......@@ -141,7 +141,7 @@ dependencies, and perhaps some data files and scripts::
'': ['*.txt', '*.rst'],
# And include any *.msg files found in the 'hello' package, too:
'hello': ['*.msg'],
}
},
# metadata for upload to PyPI
author = "Me",
......@@ -1117,7 +1117,9 @@ if they do, it might not be the right version. Fixing this is easy; just
download `distribute_setup.py`_, and put it in the same directory as your ``setup.py``
script. (Be sure to add it to your revision control system, too.) Then add
these two lines to the very top of your setup script, before the script imports
anything from setuptools::
anything from setuptools:
.. code-block:: python
import distribute_setup
distribute_setup.use_setuptools()
......@@ -1573,7 +1575,9 @@ Managing "Continuous Releases" Using Subversion
If you expect your users to track in-development versions of your project via
Subversion, there are a few additional steps you should take to ensure that
things work smoothly with EasyInstall. First, you should add the following
to your project's ``setup.cfg`` file::
to your project's ``setup.cfg`` file:
.. code-block:: ini
[egg_info]
tag_build = .dev
......@@ -1603,7 +1607,9 @@ their checkout URL (as described in the previous section) with an
to download ``projectname==dev`` in order to get the latest in-development
code. Note that if your project depends on such in-progress code, you may wish
to specify your ``install_requires`` (or other requirements) to include
``==dev``, e.g.::
``==dev``, e.g.:
.. code-block:: python
install_requires = ["OtherProject>=0.2a1.dev-r143,==dev"]
......@@ -2369,6 +2375,63 @@ The ``upload`` command has a few options worth noting:
The URL of the repository to upload to. Defaults to
http://pypi.python.org/pypi (i.e., the main PyPI installation).
.. _upload_docs:
``upload_docs`` - Upload package documentation to PyPI
======================================================
PyPI now supports uploading project documentation to the dedicated URL
http://packages.python.org/<project>/.
The ``upload_docs`` command will create the necessary zip file out of a
documentation directory and will post to the repository.
Note that to upload the documentation of a project, the corresponding version
must already be registered with PyPI, using the distutils ``register``
command -- just like the ``upload`` command.
Assuming there is an ``Example`` project with documentation in the
subdirectory ``docs``, e.g.::
Example/
|-- example.py
|-- setup.cfg
|-- setup.py
|-- docs
| |-- build
| | `-- html
| | | |-- index.html
| | | `-- tips_tricks.html
| |-- conf.py
| |-- index.txt
| `-- tips_tricks.txt
You can simply pass the documentation directory path to the ``upload_docs``
command::
python setup.py upload_docs --upload-dir=docs/build/html
As with any other ``setuptools`` based command, you can define useful
defaults in the ``setup.cfg`` of your Python project, e.g.:
.. code-block:: ini
[upload_docs]
upload-dir = docs/build/html
The ``upload_docs`` command has the following options:
``--upload-dir``
The directory to be uploaded to the repository.
``--show-response``
Display the full response text from server; this is useful for debugging
PyPI problems.
``--repository=URL, -r URL``
The URL of the repository to upload to. Defaults to
http://pypi.python.org/pypi (i.e., the main PyPI installation).
------------------------------------
Extending and Reusing ``setuptools``
......@@ -2539,7 +2602,9 @@ all the filenames within that directory (and any subdirectories thereof) that
are under revision control.
For example, if you were going to create a plugin for a revision control system
called "foobar", you would write a function something like this::
called "foobar", you would write a function something like this:
.. code-block:: python
def find_files_for_foobar(dirname):
# loop to yield paths that start with `dirname`
......
......@@ -6,3 +6,11 @@ tag_svn_revision = 1
release = egg_info -RDb ''
source = register sdist binary
binary = bdist_egg upload --show-response
[build_sphinx]
source-dir = docs/
build-dir = docs/build
all_files = 1
[upload_docs]
upload-dir = docs/build/html
\ No newline at end of file
......@@ -134,6 +134,7 @@ dist = setup(
License :: OSI Approved :: Zope Public License
Operating System :: OS Independent
Programming Language :: Python
Programming Language :: Python :: 3
Topic :: Software Development :: Libraries :: Python Modules
Topic :: System :: Archiving :: Packaging
Topic :: System :: Systems Administration
......
......@@ -2,7 +2,7 @@ __all__ = [
'alias', 'bdist_egg', 'bdist_rpm', 'build_ext', 'build_py', 'develop',
'easy_install', 'egg_info', 'install', 'install_lib', 'rotate', 'saveopts',
'sdist', 'setopt', 'test', 'upload', 'install_egg_info', 'install_scripts',
'register', 'bdist_wininst',
'register', 'bdist_wininst', 'upload_docs',
]
import sys
......
# -*- coding: utf-8 -*-
"""upload_docs
Implements a Distutils 'upload_docs' subcommand (upload documentation to
PyPI's packages.python.org).
"""
import os
import socket
import zipfile
import httplib
import base64
import urlparse
import tempfile
import cStringIO as StringIO
from distutils import log
from distutils.errors import DistutilsOptionError
from distutils.command.upload import upload
class upload_docs(upload):
description = 'Upload documentation to PyPI'
user_options = [
('repository=', 'r',
"url of repository [default: %s]" % upload.DEFAULT_REPOSITORY),
('show-response', None,
'display full response text from server'),
('upload-dir=', None, 'directory to upload'),
]
boolean_options = upload.boolean_options
def initialize_options(self):
upload.initialize_options(self)
self.upload_dir = None
def finalize_options(self):
upload.finalize_options(self)
if self.upload_dir is None:
build = self.get_finalized_command('build')
self.upload_dir = os.path.join(build.build_base, 'docs')
self.mkpath(self.upload_dir)
self.ensure_dirname('upload_dir')
self.announce('Using upload directory %s' % self.upload_dir)
def create_zipfile(self):
name = self.distribution.metadata.get_name()
tmp_dir = tempfile.mkdtemp()
tmp_file = os.path.join(tmp_dir, "%s.zip" % name)
zip_file = zipfile.ZipFile(tmp_file, "w")
for root, dirs, files in os.walk(self.upload_dir):
if not files:
raise DistutilsOptionError(
"no files found in upload directory '%s'"
% self.upload_dir)
for name in files:
full = os.path.join(root, name)
relative = root[len(self.upload_dir):].lstrip(os.path.sep)
dest = os.path.join(relative, name)
zip_file.write(full, dest)
zip_file.close()
return tmp_file
def run(self):
zip_file = self.create_zipfile()
self.upload_file(zip_file)
def upload_file(self, filename):
content = open(filename, 'rb').read()
meta = self.distribution.metadata
data = {
':action': 'doc_upload',
'name': meta.get_name(),
'content': (os.path.basename(filename), content),
}
# set up the authentication
auth = "Basic " + base64.encodestring(
self.username + ":" + self.password).strip()
# Build up the MIME payload for the POST data
boundary = '--------------GHSKFJDLGDS7543FJKLFHRE75642756743254'
sep_boundary = '\n--' + boundary
end_boundary = sep_boundary + '--'
body = StringIO.StringIO()
for key, value in data.items():
# handle multiple entries for the same name
if type(value) != type([]):
value = [value]
for value in value:
if type(value) is tuple:
fn = ';filename="%s"' % value[0]
value = value[1]
else:
fn = ""
value = str(value)
body.write(sep_boundary)
body.write('\nContent-Disposition: form-data; name="%s"'%key)
body.write(fn)
body.write("\n\n")
body.write(value)
if value and value[-1] == '\r':
body.write('\n') # write an extra newline (lurve Macs)
body.write(end_boundary)
body.write("\n")
body = body.getvalue()
self.announce("Submitting documentation to %s" % (self.repository),
log.INFO)
# build the Request
# We can't use urllib2 since we need to send the Basic
# auth right with the first request
schema, netloc, url, params, query, fragments = \
urlparse.urlparse(self.repository)
assert not params and not query and not fragments
if schema == 'http':
http = httplib.HTTPConnection(netloc)
elif schema == 'https':
http = httplib.HTTPSConnection(netloc)
else:
raise AssertionError("unsupported schema "+schema)
data = ''
loglevel = log.INFO
try:
http.connect()
http.putrequest("POST", url)
http.putheader('Content-type',
'multipart/form-data; boundary=%s'%boundary)
http.putheader('Content-length', str(len(body)))
http.putheader('Authorization', auth)
http.endheaders()
http.send(body)
except socket.error, e:
self.announce(str(e), log.ERROR)
return
r = http.getresponse()
if r.status == 200:
self.announce('Server response (%s): %s' % (r.status, r.reason),
log.INFO)
elif r.status == 301:
location = r.getheader('Location')
if location is None:
location = 'http://packages.python.org/%s/' % meta.get_name()
self.announce('Upload successful. Visit %s' % location,
log.INFO)
else:
self.announce('Upload failed (%s): %s' % (r.status, r.reason),
log.ERROR)
if self.show_response:
print '-'*75, r.read(), '-'*75
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment