From c74ff2a16e47bdf31f8ad17bbfbe2da5d03803c6 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 10 Jan 2014 19:26:04 -0800 Subject: Import paramiko.org repository @ 3ac370054ef10fb060fe75fff25fe3a70ecc02c0 --- site/_static/logo.png | Bin 0 -> 6401 bytes site/_templates/rss.xml | 19 +++++++ site/blog.py | 140 ++++++++++++++++++++++++++++++++++++++++++++++ site/blog.rst | 16 ++++++ site/blog/first-post.rst | 7 +++ site/blog/second-post.rst | 7 +++ site/conf.py | 55 ++++++++++++++++++ site/contact.rst | 11 ++++ site/contributing.rst | 19 +++++++ site/dev-requirements.txt | 3 + site/index.rst | 31 ++++++++++ site/installing.rst | 105 ++++++++++++++++++++++++++++++++++ site/tasks.py | 19 +++++++ 13 files changed, 432 insertions(+) create mode 100644 site/_static/logo.png create mode 100644 site/_templates/rss.xml create mode 100644 site/blog.py create mode 100644 site/blog.rst create mode 100644 site/blog/first-post.rst create mode 100644 site/blog/second-post.rst create mode 100644 site/conf.py create mode 100644 site/contact.rst create mode 100644 site/contributing.rst create mode 100644 site/dev-requirements.txt create mode 100644 site/index.rst create mode 100644 site/installing.rst create mode 100644 site/tasks.py diff --git a/site/_static/logo.png b/site/_static/logo.png new file mode 100644 index 00000000..bc76697e Binary files /dev/null and b/site/_static/logo.png differ diff --git a/site/_templates/rss.xml b/site/_templates/rss.xml new file mode 100644 index 00000000..f6f9cbd1 --- /dev/null +++ b/site/_templates/rss.xml @@ -0,0 +1,19 @@ + + + + + {{ title }} + {{ link }} + {{ description }} + {{ date }} + {% for link, title, desc, date in posts %} + + {{ link }} + {{ link }} + <![CDATA[{{ title }}]]> + + {{ date }} + + {% endfor %} + + diff --git a/site/blog.py b/site/blog.py new file mode 100644 index 00000000..3b129ebf --- /dev/null +++ b/site/blog.py @@ -0,0 +1,140 @@ +from collections import namedtuple +from datetime import datetime +import time +import email.utils + +from sphinx.util.compat import Directive +from docutils import nodes + + +class BlogDateDirective(Directive): + """ + Used to parse/attach date info to blog post documents. + + No nodes generated, since none are needed. + """ + has_content = True + + def run(self): + # Tag parent document with parsed date value. + self.state.document.blog_date = datetime.strptime( + self.content[0], "%Y-%m-%d" + ) + # Don't actually insert any nodes, we're already done. + return [] + +class blog_post_list(nodes.General, nodes.Element): + pass + +class BlogPostListDirective(Directive): + """ + Simply spits out a 'blog_post_list' temporary node for replacement. + + Gets replaced at doctree-resolved time - only then will all blog post + documents be written out (& their date directives executed). + """ + def run(self): + return [blog_post_list('')] + + +Post = namedtuple('Post', 'name doc title date opener') + +def get_posts(app): + # Obtain blog posts + post_names = filter(lambda x: x.startswith('blog/'), app.env.found_docs) + posts = map(lambda x: (x, app.env.get_doctree(x)), post_names) + # Obtain common data used for list page & RSS + data = [] + for post, doc in sorted(posts, key=lambda x: x[1].blog_date, reverse=True): + # Welp. No "nice" way to get post title. Thanks Sphinx. + title = doc[0][0][0] + # Date. This may or may not end up reflecting the required + # *input* format, but doing it here gives us flexibility. + date = doc.blog_date + # 1st paragraph as opener. TODO: allow a role or something marking + # where to actually pull from? + opener = doc.traverse(nodes.paragraph)[0] + data.append(Post(post, doc, title, date, opener)) + return data + +def replace_blog_post_lists(app, doctree, fromdocname): + """ + Replace blog_post_list nodes with ordered list-o-links to posts. + """ + # Obtain blog posts + post_names = filter(lambda x: x.startswith('blog/'), app.env.found_docs) + posts = map(lambda x: (x, app.env.get_doctree(x)), post_names) + # Build "list" of links/etc + post_links = [] + for post, doc, title, date, opener in get_posts(app): + # Link itself + uri = app.builder.get_relative_uri(fromdocname, post) + link = nodes.reference('', '', refdocname=post, refuri=uri) + # Title, bolded. TODO: use 'topic' or something maybe? + link.append(nodes.strong('', title)) + date = date.strftime("%Y-%m-%d") + # Meh @ not having great docutils nodes which map to this. + html = '
%s
' % date + timestamp = nodes.raw(text=html, format='html') + # NOTE: may group these within another element later if styling + # necessitates it + group = [timestamp, nodes.paragraph('', '', link), opener] + post_links.extend(group) + + # Replace temp node(s) w/ expanded list-o-links + for node in doctree.traverse(blog_post_list): + node.replace_self(post_links) + +def rss_timestamp(timestamp): + # Use horribly inappropriate module for its magical daylight-savings-aware + # timezone madness. Props to Tinkerer for the idea. + return email.utils.formatdate( + time.mktime(timestamp.timetuple()), + localtime=True + ) + +def generate_rss(app): + # Meh at having to run this subroutine like 3x per build. Not worth trying + # to be clever for now tho. + posts_ = get_posts(app) + # LOL URLs + root = app.config.rss_link + if not root.endswith('/'): + root += '/' + # Oh boy + posts = [ + ( + root + app.builder.get_target_uri(x.name), + x.title, + str(x.opener[0]), # Grab inner text element from paragraph + rss_timestamp(x.date), + ) + for x in posts_ + ] + location = 'blog/rss.xml' + context = { + 'title': app.config.project, + 'link': root, + 'atom': root + location, + 'description': app.config.rss_description, + # 'posts' is sorted by date already + 'date': rss_timestamp(posts_[0].date), + 'posts': posts, + } + yield (location, context, 'rss.xml') + +def setup(app): + # Link in RSS feed back to main website, e.g. 'http://paramiko.org' + app.add_config_value('rss_link', None, '') + # Ditto for RSS description field + app.add_config_value('rss_description', None, '') + # Interprets date metadata in blog post documents + app.add_directive('date', BlogDateDirective) + # Inserts blog post list node (in e.g. a listing page) for replacement + # below + app.add_node(blog_post_list) + app.add_directive('blog-posts', BlogPostListDirective) + # Performs abovementioned replacement + app.connect('doctree-resolved', replace_blog_post_lists) + # Generates RSS page from whole cloth at page generation step + app.connect('html-collect-pages', generate_rss) diff --git a/site/blog.rst b/site/blog.rst new file mode 100644 index 00000000..af9651e4 --- /dev/null +++ b/site/blog.rst @@ -0,0 +1,16 @@ +==== +Blog +==== + +.. blog-posts directive gets replaced with an ordered list of blog posts. + +.. blog-posts:: + + +.. The following toctree ensures blog posts get processed. + +.. toctree:: + :hidden: + :glob: + + blog/* diff --git a/site/blog/first-post.rst b/site/blog/first-post.rst new file mode 100644 index 00000000..7b075073 --- /dev/null +++ b/site/blog/first-post.rst @@ -0,0 +1,7 @@ +=========== +First post! +=========== + +A blog post. + +.. date:: 2013-12-04 diff --git a/site/blog/second-post.rst b/site/blog/second-post.rst new file mode 100644 index 00000000..c4463f33 --- /dev/null +++ b/site/blog/second-post.rst @@ -0,0 +1,7 @@ +=========== +Another one +=========== + +.. date:: 2013-12-05 + +Indeed! diff --git a/site/conf.py b/site/conf.py new file mode 100644 index 00000000..8c6f3aa4 --- /dev/null +++ b/site/conf.py @@ -0,0 +1,55 @@ +from datetime import datetime +import os +import sys + +import alabaster + + +# Add local blog extension +sys.path.append(os.path.abspath('.')) +extensions = ['blog'] +rss_link = 'http://paramiko.org' +rss_description = 'Paramiko project news' + +# Alabaster theme +html_theme_path = [alabaster.get_path()] +html_static_path = ['_static'] +html_theme = 'alabaster' +html_theme_options = { + 'logo': 'logo.png', + 'logo_name': 'true', + 'description': "A Python implementation of SSHv2.", + 'github_user': 'paramiko', + 'github_repo': 'paramiko', + 'gittip_user': 'bitprophet', + 'analytics_id': 'UA-18486793-2', + + 'link': '#3782BE', + 'link_hover': '#3782BE', + +} +html_sidebars = { + # Landing page (no ToC) + 'index': [ + 'about.html', + 'searchbox.html', + 'donate.html', + ], + # Inner pages get a ToC + '**': [ + 'about.html', + 'localtoc.html', + 'searchbox.html', + 'donate.html', + ] +} + +# Regular settings +project = u'Paramiko' +year = datetime.now().year +copyright = u'%d Jeff Forcier, 2003-2012 Robey Pointer' % year +master_doc = 'index' +templates_path = ['_templates'] +exclude_trees = ['_build'] +source_suffix = '.rst' +default_role = 'obj' diff --git a/site/contact.rst b/site/contact.rst new file mode 100644 index 00000000..b479f170 --- /dev/null +++ b/site/contact.rst @@ -0,0 +1,11 @@ +======= +Contact +======= + +You can get in touch with the developer & user community in any of the +following ways: + +* IRC: ``#paramiko`` on Freenode +* Mailing list: ``paramiko@librelist.com`` (see `the LibreList homepage + `_ for usage details). +* This website's :doc:`blog `. diff --git a/site/contributing.rst b/site/contributing.rst new file mode 100644 index 00000000..b121e64b --- /dev/null +++ b/site/contributing.rst @@ -0,0 +1,19 @@ +============ +Contributing +============ + +How to get the code +=================== + +Our primary Git repository is on Github at `paramiko/paramiko +`; please follow their instruction for +cloning to your local system. (If you intend to submit patches/pull requests, +we recommend forking first, then cloning your fork. Github has excellent +documentation for all this.) + + +How to submit bug reports or new code +===================================== + +Please see `this project-agnostic contribution guide +`_ - we follow it explicitly. diff --git a/site/dev-requirements.txt b/site/dev-requirements.txt new file mode 100644 index 00000000..524b8060 --- /dev/null +++ b/site/dev-requirements.txt @@ -0,0 +1,3 @@ +invoke>=0.6.1 +invocations>=0.4.4 +sphinx==1.1.3 diff --git a/site/index.rst b/site/index.rst new file mode 100644 index 00000000..7d203b62 --- /dev/null +++ b/site/index.rst @@ -0,0 +1,31 @@ +Welcome to Paramiko! +==================== + +Paramiko is a Python (2.5+) implementation of the SSHv2 protocol [#]_, +providing both client and server functionality. While it leverages a Python C +extension for low level cryptography (`PyCrypto `_), +Paramiko itself is a pure Python interface around SSH networking concepts. + +This website covers project information for Paramiko such as contribution +guidelines, development roadmap, news/blog, and so forth. Detailed +usage and API documentation can be found at our code documentation site, +`docs.paramiko.org `_. + +.. toctree:: + blog + installing + contributing + contact + + +.. rubric:: Footnotes + +.. [#] + SSH is defined in RFCs + `4251 `_, + `4252 `_, + `4253 `_, and + `4254 `_; + the primary working implementation of the protocol is the `OpenSSH project + `_. Paramiko implements a large portion of the SSH + feature set, but there are occasional gaps. diff --git a/site/installing.rst b/site/installing.rst new file mode 100644 index 00000000..0d4dc1ac --- /dev/null +++ b/site/installing.rst @@ -0,0 +1,105 @@ +========== +Installing +========== + +Paramiko itself +=============== + +The recommended way to get Invoke is to **install the latest stable release** +via `pip `_:: + + $ pip install paramiko + +.. note:: + Users who want the bleeding edge can install the development version via + ``pip install paramiko==dev``. + +We currently support **Python 2.5/2.6/2.7**, with support for Python 3 coming +soon. Users on Python 2.4 or older are urged to upgrade. Paramiko *may* work on +Python 2.4 still, but there is no longer any support guarantee. + +Paramiko has two dependencies: the pure-Python ECDSA module `ecdsa`, and the +PyCrypto C extension. `ecdsa` is easily installable from wherever you +obtained Paramiko's package; PyCrypto may require more work. Read on for +details. + +PyCrypto +======== + +`PyCrypto `_ provides the low-level +(C-based) encryption algorithms we need to implement the SSH protocol. There +are a couple gotchas associated with installing PyCrypto: its compatibility +with Python's package tools, and the fact that it is a C-based extension. + +.. _pycrypto-and-pip: + +Possible gotcha on older Python and/or pip versions +--------------------------------------------------- + +We strongly recommend using ``pip`` to as it is newer and generally better than +``easy_install``. However, a combination of bugs in specific (now rather old) +versions of Python, ``pip`` and PyCrypto can prevent installation of PyCrypto. +Specifically: + +* Python = 2.5.x +* PyCrypto >= 2.1 (required for most modern versions of Paramiko) +* ``pip`` < 0.8.1 + +When all three criteria are met, you may encounter ``No such file or +directory`` IOErrors when trying to ``pip install paramiko`` or ``pip install +PyCrypto``. + +The fix is to make sure at least one of the above criteria is not met, by doing +the following (in order of preference): + +* Upgrade to ``pip`` 0.8.1 or above, e.g. by running ``pip install -U pip``. +* Upgrade to Python 2.6 or above. +* Downgrade to Paramiko 1.7.6 or 1.7.7, which do not require PyCrypto >= 2.1, + and install PyCrypto 2.0.1 (the oldest version on PyPI which works with + Paramiko 1.7.6/1.7.7) + + +C extension +----------- + +Unless you are installing from a precompiled source such as a Debian apt +repository or RedHat RPM, or using :ref:`pypm `, you will also need the +ability to build Python C-based modules from source in order to install +PyCrypto. Users on **Unix-based platforms** such as Ubuntu or Mac OS X will +need the traditional C build toolchain installed (e.g. Developer Tools / XCode +Tools on the Mac, or the ``build-essential`` package on Ubuntu or Debian Linux +-- basically, anything with ``gcc``, ``make`` and so forth) as well as the +Python development libraries, often named ``python-dev`` or similar. + +For **Windows** users we recommend using :ref:`pypm`, installing a C +development environment such as `Cygwin `_ or obtaining a +precompiled Win32 PyCrypto package from `voidspace's Python modules page +`_. + +.. note:: + Some Windows users whose Python is 64-bit have found that the PyCrypto + dependency ``winrandom`` may not install properly, leading to ImportErrors. + In this scenario, you'll probably need to compile ``winrandom`` yourself + via e.g. MS Visual Studio. See `Fabric #194 + `_ for info. + + +.. _pypm: + +ActivePython and PyPM +===================== + +Windows users who already have ActiveState's `ActivePython +`_ distribution installed +may find Paramiko is best installed with `its package manager, PyPM +`_. Below is example output from an +installation of Paramiko via ``pypm``:: + + C:\> pypm install paramiko + The following packages will be installed into "%APPDATA%\Python" (2.7): + paramiko-1.7.8 pycrypto-2.4 + Get: [pypm-free.activestate.com] paramiko 1.7.8 + Get: [pypm-free.activestate.com] pycrypto 2.4 + Installing paramiko-1.7.8 + Installing pycrypto-2.4 + C:\> diff --git a/site/tasks.py b/site/tasks.py new file mode 100644 index 00000000..e2d952b1 --- /dev/null +++ b/site/tasks.py @@ -0,0 +1,19 @@ +from invoke import Collection +from invocations import docs, testing + +# TODO: let from_module specify new name +api = Collection.from_module(docs) +# TODO: maybe allow rolling configuration into it too heh +api.configure({ + 'sphinx.source': 'api', + 'sphinx.target': 'api/_build', +}) +api.name = 'api' +site = Collection.from_module(docs) +site.name = 'site' +site.configure({ + 'sphinx.source': 'site', + 'sphinx.target': 'site/_build', +}) + +ns = Collection(testing.test, api=api, site=site) -- cgit v1.2.3 From 7d56ecb1a7d1654ae971e9896aa26e938454d3ea Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Fri, 10 Jan 2014 20:07:43 -0800 Subject: Meta prep work (reqs.txt, tasks.py) --- .gitignore | 1 + .travis.yml | 4 +++- dev-requirements.txt | 6 ++++++ requirements.txt | 2 -- site/dev-requirements.txt | 3 --- site/tasks.py | 19 ------------------- tasks.py | 20 ++++++++++++++++++++ tox-requirements.txt | 2 ++ tox.ini | 2 +- 9 files changed, 33 insertions(+), 26 deletions(-) create mode 100644 dev-requirements.txt delete mode 100644 requirements.txt delete mode 100644 site/dev-requirements.txt delete mode 100644 site/tasks.py create mode 100644 tasks.py create mode 100644 tox-requirements.txt diff --git a/.gitignore b/.gitignore index 4b578950..a125b270 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ dist/ paramiko.egg-info/ test.log docs/ +_build diff --git a/.travis.yml b/.travis.yml index c9802a80..29e44e53 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,9 @@ python: install: # Self-install for setup.py-driven deps - pip install -e . - - pip install coveralls + # Dev (doc/test running) requirements + - pip install coveralls # For coveralls.io specifically + - pip install -r dev-requirements.txt script: coverage run --source=paramiko test.py --verbose notifications: irc: diff --git a/dev-requirements.txt b/dev-requirements.txt new file mode 100644 index 00000000..59a1f144 --- /dev/null +++ b/dev-requirements.txt @@ -0,0 +1,6 @@ +# For newer tasks like building Sphinx docs. +# NOTE: Requires Python >=2.6 +invoke>=0.6.1 +invocations>=0.4.4 +sphinx>=1.1.3 +alabaster>=0.1.0 diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 75112a23..00000000 --- a/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -pycrypto -tox diff --git a/site/dev-requirements.txt b/site/dev-requirements.txt deleted file mode 100644 index 524b8060..00000000 --- a/site/dev-requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -invoke>=0.6.1 -invocations>=0.4.4 -sphinx==1.1.3 diff --git a/site/tasks.py b/site/tasks.py deleted file mode 100644 index e2d952b1..00000000 --- a/site/tasks.py +++ /dev/null @@ -1,19 +0,0 @@ -from invoke import Collection -from invocations import docs, testing - -# TODO: let from_module specify new name -api = Collection.from_module(docs) -# TODO: maybe allow rolling configuration into it too heh -api.configure({ - 'sphinx.source': 'api', - 'sphinx.target': 'api/_build', -}) -api.name = 'api' -site = Collection.from_module(docs) -site.name = 'site' -site.configure({ - 'sphinx.source': 'site', - 'sphinx.target': 'site/_build', -}) - -ns = Collection(testing.test, api=api, site=site) diff --git a/tasks.py b/tasks.py new file mode 100644 index 00000000..d470dab0 --- /dev/null +++ b/tasks.py @@ -0,0 +1,20 @@ +from invoke import Collection +from invocations import docs, testing + + +# TODO: let from_module specify new name +api = Collection.from_module(docs) +# TODO: maybe allow rolling configuration into it too heh +api.configure({ + 'sphinx.source': 'api', + 'sphinx.target': 'api/_build', +}) +api.name = 'api' +site = Collection.from_module(docs) +site.name = 'site' +site.configure({ + 'sphinx.source': 'site', + 'sphinx.target': 'site/_build', +}) + +ns = Collection(testing.test, api=api, site=site) diff --git a/tox-requirements.txt b/tox-requirements.txt new file mode 100644 index 00000000..26224ce6 --- /dev/null +++ b/tox-requirements.txt @@ -0,0 +1,2 @@ +# Not sure why tox can't just read setup.py? +pycrypto diff --git a/tox.ini b/tox.ini index 6cb80012..af4fbf20 100644 --- a/tox.ini +++ b/tox.ini @@ -2,5 +2,5 @@ envlist = py25,py26,py27 [testenv] -commands = pip install --use-mirrors -q -r requirements.txt +commands = pip install --use-mirrors -q -r tox-requirements.txt python test.py -- cgit v1.2.3 From ccb7a6c2cd22689d363a03da2c7a2bcf4e27a0c8 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Mon, 13 Jan 2014 12:17:46 -0800 Subject: Start fleshing out two-site setup --- .gitignore | 1 + site/_static/logo.png | Bin 6401 -> 0 bytes site/_templates/rss.xml | 19 ------ site/blog.py | 140 ---------------------------------------- site/blog.rst | 16 ----- site/blog/first-post.rst | 7 -- site/blog/second-post.rst | 7 -- site/conf.py | 55 ---------------- site/contact.rst | 11 ---- site/contributing.rst | 19 ------ site/index.rst | 31 --------- site/installing.rst | 105 ------------------------------ sites/_shared_static/logo.png | Bin 0 -> 6401 bytes sites/docs/conf.py | 4 ++ sites/docs/index.rst | 6 ++ sites/main/_templates/rss.xml | 19 ++++++ sites/main/blog.py | 140 ++++++++++++++++++++++++++++++++++++++++ sites/main/blog.rst | 16 +++++ sites/main/blog/first-post.rst | 7 ++ sites/main/blog/second-post.rst | 7 ++ sites/main/conf.py | 4 ++ sites/main/contact.rst | 11 ++++ sites/main/contributing.rst | 19 ++++++ sites/main/index.rst | 31 +++++++++ sites/main/installing.rst | 105 ++++++++++++++++++++++++++++++ sites/shared_conf.py | 56 ++++++++++++++++ tasks.py | 18 +++--- 27 files changed, 435 insertions(+), 419 deletions(-) delete mode 100644 site/_static/logo.png delete mode 100644 site/_templates/rss.xml delete mode 100644 site/blog.py delete mode 100644 site/blog.rst delete mode 100644 site/blog/first-post.rst delete mode 100644 site/blog/second-post.rst delete mode 100644 site/conf.py delete mode 100644 site/contact.rst delete mode 100644 site/contributing.rst delete mode 100644 site/index.rst delete mode 100644 site/installing.rst create mode 100644 sites/_shared_static/logo.png create mode 100644 sites/docs/conf.py create mode 100644 sites/docs/index.rst create mode 100644 sites/main/_templates/rss.xml create mode 100644 sites/main/blog.py create mode 100644 sites/main/blog.rst create mode 100644 sites/main/blog/first-post.rst create mode 100644 sites/main/blog/second-post.rst create mode 100644 sites/main/conf.py create mode 100644 sites/main/contact.rst create mode 100644 sites/main/contributing.rst create mode 100644 sites/main/index.rst create mode 100644 sites/main/installing.rst create mode 100644 sites/shared_conf.py diff --git a/.gitignore b/.gitignore index a125b270..9e1febf3 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ dist/ paramiko.egg-info/ test.log docs/ +!sites/docs _build diff --git a/site/_static/logo.png b/site/_static/logo.png deleted file mode 100644 index bc76697e..00000000 Binary files a/site/_static/logo.png and /dev/null differ diff --git a/site/_templates/rss.xml b/site/_templates/rss.xml deleted file mode 100644 index f6f9cbd1..00000000 --- a/site/_templates/rss.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - {{ title }} - {{ link }} - {{ description }} - {{ date }} - {% for link, title, desc, date in posts %} - - {{ link }} - {{ link }} - <![CDATA[{{ title }}]]> - - {{ date }} - - {% endfor %} - - diff --git a/site/blog.py b/site/blog.py deleted file mode 100644 index 3b129ebf..00000000 --- a/site/blog.py +++ /dev/null @@ -1,140 +0,0 @@ -from collections import namedtuple -from datetime import datetime -import time -import email.utils - -from sphinx.util.compat import Directive -from docutils import nodes - - -class BlogDateDirective(Directive): - """ - Used to parse/attach date info to blog post documents. - - No nodes generated, since none are needed. - """ - has_content = True - - def run(self): - # Tag parent document with parsed date value. - self.state.document.blog_date = datetime.strptime( - self.content[0], "%Y-%m-%d" - ) - # Don't actually insert any nodes, we're already done. - return [] - -class blog_post_list(nodes.General, nodes.Element): - pass - -class BlogPostListDirective(Directive): - """ - Simply spits out a 'blog_post_list' temporary node for replacement. - - Gets replaced at doctree-resolved time - only then will all blog post - documents be written out (& their date directives executed). - """ - def run(self): - return [blog_post_list('')] - - -Post = namedtuple('Post', 'name doc title date opener') - -def get_posts(app): - # Obtain blog posts - post_names = filter(lambda x: x.startswith('blog/'), app.env.found_docs) - posts = map(lambda x: (x, app.env.get_doctree(x)), post_names) - # Obtain common data used for list page & RSS - data = [] - for post, doc in sorted(posts, key=lambda x: x[1].blog_date, reverse=True): - # Welp. No "nice" way to get post title. Thanks Sphinx. - title = doc[0][0][0] - # Date. This may or may not end up reflecting the required - # *input* format, but doing it here gives us flexibility. - date = doc.blog_date - # 1st paragraph as opener. TODO: allow a role or something marking - # where to actually pull from? - opener = doc.traverse(nodes.paragraph)[0] - data.append(Post(post, doc, title, date, opener)) - return data - -def replace_blog_post_lists(app, doctree, fromdocname): - """ - Replace blog_post_list nodes with ordered list-o-links to posts. - """ - # Obtain blog posts - post_names = filter(lambda x: x.startswith('blog/'), app.env.found_docs) - posts = map(lambda x: (x, app.env.get_doctree(x)), post_names) - # Build "list" of links/etc - post_links = [] - for post, doc, title, date, opener in get_posts(app): - # Link itself - uri = app.builder.get_relative_uri(fromdocname, post) - link = nodes.reference('', '', refdocname=post, refuri=uri) - # Title, bolded. TODO: use 'topic' or something maybe? - link.append(nodes.strong('', title)) - date = date.strftime("%Y-%m-%d") - # Meh @ not having great docutils nodes which map to this. - html = '
%s
' % date - timestamp = nodes.raw(text=html, format='html') - # NOTE: may group these within another element later if styling - # necessitates it - group = [timestamp, nodes.paragraph('', '', link), opener] - post_links.extend(group) - - # Replace temp node(s) w/ expanded list-o-links - for node in doctree.traverse(blog_post_list): - node.replace_self(post_links) - -def rss_timestamp(timestamp): - # Use horribly inappropriate module for its magical daylight-savings-aware - # timezone madness. Props to Tinkerer for the idea. - return email.utils.formatdate( - time.mktime(timestamp.timetuple()), - localtime=True - ) - -def generate_rss(app): - # Meh at having to run this subroutine like 3x per build. Not worth trying - # to be clever for now tho. - posts_ = get_posts(app) - # LOL URLs - root = app.config.rss_link - if not root.endswith('/'): - root += '/' - # Oh boy - posts = [ - ( - root + app.builder.get_target_uri(x.name), - x.title, - str(x.opener[0]), # Grab inner text element from paragraph - rss_timestamp(x.date), - ) - for x in posts_ - ] - location = 'blog/rss.xml' - context = { - 'title': app.config.project, - 'link': root, - 'atom': root + location, - 'description': app.config.rss_description, - # 'posts' is sorted by date already - 'date': rss_timestamp(posts_[0].date), - 'posts': posts, - } - yield (location, context, 'rss.xml') - -def setup(app): - # Link in RSS feed back to main website, e.g. 'http://paramiko.org' - app.add_config_value('rss_link', None, '') - # Ditto for RSS description field - app.add_config_value('rss_description', None, '') - # Interprets date metadata in blog post documents - app.add_directive('date', BlogDateDirective) - # Inserts blog post list node (in e.g. a listing page) for replacement - # below - app.add_node(blog_post_list) - app.add_directive('blog-posts', BlogPostListDirective) - # Performs abovementioned replacement - app.connect('doctree-resolved', replace_blog_post_lists) - # Generates RSS page from whole cloth at page generation step - app.connect('html-collect-pages', generate_rss) diff --git a/site/blog.rst b/site/blog.rst deleted file mode 100644 index af9651e4..00000000 --- a/site/blog.rst +++ /dev/null @@ -1,16 +0,0 @@ -==== -Blog -==== - -.. blog-posts directive gets replaced with an ordered list of blog posts. - -.. blog-posts:: - - -.. The following toctree ensures blog posts get processed. - -.. toctree:: - :hidden: - :glob: - - blog/* diff --git a/site/blog/first-post.rst b/site/blog/first-post.rst deleted file mode 100644 index 7b075073..00000000 --- a/site/blog/first-post.rst +++ /dev/null @@ -1,7 +0,0 @@ -=========== -First post! -=========== - -A blog post. - -.. date:: 2013-12-04 diff --git a/site/blog/second-post.rst b/site/blog/second-post.rst deleted file mode 100644 index c4463f33..00000000 --- a/site/blog/second-post.rst +++ /dev/null @@ -1,7 +0,0 @@ -=========== -Another one -=========== - -.. date:: 2013-12-05 - -Indeed! diff --git a/site/conf.py b/site/conf.py deleted file mode 100644 index 8c6f3aa4..00000000 --- a/site/conf.py +++ /dev/null @@ -1,55 +0,0 @@ -from datetime import datetime -import os -import sys - -import alabaster - - -# Add local blog extension -sys.path.append(os.path.abspath('.')) -extensions = ['blog'] -rss_link = 'http://paramiko.org' -rss_description = 'Paramiko project news' - -# Alabaster theme -html_theme_path = [alabaster.get_path()] -html_static_path = ['_static'] -html_theme = 'alabaster' -html_theme_options = { - 'logo': 'logo.png', - 'logo_name': 'true', - 'description': "A Python implementation of SSHv2.", - 'github_user': 'paramiko', - 'github_repo': 'paramiko', - 'gittip_user': 'bitprophet', - 'analytics_id': 'UA-18486793-2', - - 'link': '#3782BE', - 'link_hover': '#3782BE', - -} -html_sidebars = { - # Landing page (no ToC) - 'index': [ - 'about.html', - 'searchbox.html', - 'donate.html', - ], - # Inner pages get a ToC - '**': [ - 'about.html', - 'localtoc.html', - 'searchbox.html', - 'donate.html', - ] -} - -# Regular settings -project = u'Paramiko' -year = datetime.now().year -copyright = u'%d Jeff Forcier, 2003-2012 Robey Pointer' % year -master_doc = 'index' -templates_path = ['_templates'] -exclude_trees = ['_build'] -source_suffix = '.rst' -default_role = 'obj' diff --git a/site/contact.rst b/site/contact.rst deleted file mode 100644 index b479f170..00000000 --- a/site/contact.rst +++ /dev/null @@ -1,11 +0,0 @@ -======= -Contact -======= - -You can get in touch with the developer & user community in any of the -following ways: - -* IRC: ``#paramiko`` on Freenode -* Mailing list: ``paramiko@librelist.com`` (see `the LibreList homepage - `_ for usage details). -* This website's :doc:`blog `. diff --git a/site/contributing.rst b/site/contributing.rst deleted file mode 100644 index b121e64b..00000000 --- a/site/contributing.rst +++ /dev/null @@ -1,19 +0,0 @@ -============ -Contributing -============ - -How to get the code -=================== - -Our primary Git repository is on Github at `paramiko/paramiko -`; please follow their instruction for -cloning to your local system. (If you intend to submit patches/pull requests, -we recommend forking first, then cloning your fork. Github has excellent -documentation for all this.) - - -How to submit bug reports or new code -===================================== - -Please see `this project-agnostic contribution guide -`_ - we follow it explicitly. diff --git a/site/index.rst b/site/index.rst deleted file mode 100644 index 7d203b62..00000000 --- a/site/index.rst +++ /dev/null @@ -1,31 +0,0 @@ -Welcome to Paramiko! -==================== - -Paramiko is a Python (2.5+) implementation of the SSHv2 protocol [#]_, -providing both client and server functionality. While it leverages a Python C -extension for low level cryptography (`PyCrypto `_), -Paramiko itself is a pure Python interface around SSH networking concepts. - -This website covers project information for Paramiko such as contribution -guidelines, development roadmap, news/blog, and so forth. Detailed -usage and API documentation can be found at our code documentation site, -`docs.paramiko.org `_. - -.. toctree:: - blog - installing - contributing - contact - - -.. rubric:: Footnotes - -.. [#] - SSH is defined in RFCs - `4251 `_, - `4252 `_, - `4253 `_, and - `4254 `_; - the primary working implementation of the protocol is the `OpenSSH project - `_. Paramiko implements a large portion of the SSH - feature set, but there are occasional gaps. diff --git a/site/installing.rst b/site/installing.rst deleted file mode 100644 index 0d4dc1ac..00000000 --- a/site/installing.rst +++ /dev/null @@ -1,105 +0,0 @@ -========== -Installing -========== - -Paramiko itself -=============== - -The recommended way to get Invoke is to **install the latest stable release** -via `pip `_:: - - $ pip install paramiko - -.. note:: - Users who want the bleeding edge can install the development version via - ``pip install paramiko==dev``. - -We currently support **Python 2.5/2.6/2.7**, with support for Python 3 coming -soon. Users on Python 2.4 or older are urged to upgrade. Paramiko *may* work on -Python 2.4 still, but there is no longer any support guarantee. - -Paramiko has two dependencies: the pure-Python ECDSA module `ecdsa`, and the -PyCrypto C extension. `ecdsa` is easily installable from wherever you -obtained Paramiko's package; PyCrypto may require more work. Read on for -details. - -PyCrypto -======== - -`PyCrypto `_ provides the low-level -(C-based) encryption algorithms we need to implement the SSH protocol. There -are a couple gotchas associated with installing PyCrypto: its compatibility -with Python's package tools, and the fact that it is a C-based extension. - -.. _pycrypto-and-pip: - -Possible gotcha on older Python and/or pip versions ---------------------------------------------------- - -We strongly recommend using ``pip`` to as it is newer and generally better than -``easy_install``. However, a combination of bugs in specific (now rather old) -versions of Python, ``pip`` and PyCrypto can prevent installation of PyCrypto. -Specifically: - -* Python = 2.5.x -* PyCrypto >= 2.1 (required for most modern versions of Paramiko) -* ``pip`` < 0.8.1 - -When all three criteria are met, you may encounter ``No such file or -directory`` IOErrors when trying to ``pip install paramiko`` or ``pip install -PyCrypto``. - -The fix is to make sure at least one of the above criteria is not met, by doing -the following (in order of preference): - -* Upgrade to ``pip`` 0.8.1 or above, e.g. by running ``pip install -U pip``. -* Upgrade to Python 2.6 or above. -* Downgrade to Paramiko 1.7.6 or 1.7.7, which do not require PyCrypto >= 2.1, - and install PyCrypto 2.0.1 (the oldest version on PyPI which works with - Paramiko 1.7.6/1.7.7) - - -C extension ------------ - -Unless you are installing from a precompiled source such as a Debian apt -repository or RedHat RPM, or using :ref:`pypm `, you will also need the -ability to build Python C-based modules from source in order to install -PyCrypto. Users on **Unix-based platforms** such as Ubuntu or Mac OS X will -need the traditional C build toolchain installed (e.g. Developer Tools / XCode -Tools on the Mac, or the ``build-essential`` package on Ubuntu or Debian Linux --- basically, anything with ``gcc``, ``make`` and so forth) as well as the -Python development libraries, often named ``python-dev`` or similar. - -For **Windows** users we recommend using :ref:`pypm`, installing a C -development environment such as `Cygwin `_ or obtaining a -precompiled Win32 PyCrypto package from `voidspace's Python modules page -`_. - -.. note:: - Some Windows users whose Python is 64-bit have found that the PyCrypto - dependency ``winrandom`` may not install properly, leading to ImportErrors. - In this scenario, you'll probably need to compile ``winrandom`` yourself - via e.g. MS Visual Studio. See `Fabric #194 - `_ for info. - - -.. _pypm: - -ActivePython and PyPM -===================== - -Windows users who already have ActiveState's `ActivePython -`_ distribution installed -may find Paramiko is best installed with `its package manager, PyPM -`_. Below is example output from an -installation of Paramiko via ``pypm``:: - - C:\> pypm install paramiko - The following packages will be installed into "%APPDATA%\Python" (2.7): - paramiko-1.7.8 pycrypto-2.4 - Get: [pypm-free.activestate.com] paramiko 1.7.8 - Get: [pypm-free.activestate.com] pycrypto 2.4 - Installing paramiko-1.7.8 - Installing pycrypto-2.4 - C:\> diff --git a/sites/_shared_static/logo.png b/sites/_shared_static/logo.png new file mode 100644 index 00000000..bc76697e Binary files /dev/null and b/sites/_shared_static/logo.png differ diff --git a/sites/docs/conf.py b/sites/docs/conf.py new file mode 100644 index 00000000..0c7ffe55 --- /dev/null +++ b/sites/docs/conf.py @@ -0,0 +1,4 @@ +# Obtain shared config values +import os, sys +sys.path.append(os.path.abspath('..')) +from shared_conf import * diff --git a/sites/docs/index.rst b/sites/docs/index.rst new file mode 100644 index 00000000..08b34320 --- /dev/null +++ b/sites/docs/index.rst @@ -0,0 +1,6 @@ +Welcome to Paramiko's documentation! +==================================== + +This site covers Paramiko's usage & API documentation. For basic info on what +Paramiko is, including its public changelog & how the project is maintained, +please see `the main website `_. diff --git a/sites/main/_templates/rss.xml b/sites/main/_templates/rss.xml new file mode 100644 index 00000000..f6f9cbd1 --- /dev/null +++ b/sites/main/_templates/rss.xml @@ -0,0 +1,19 @@ + + + + + {{ title }} + {{ link }} + {{ description }} + {{ date }} + {% for link, title, desc, date in posts %} + + {{ link }} + {{ link }} + <![CDATA[{{ title }}]]> + + {{ date }} + + {% endfor %} + + diff --git a/sites/main/blog.py b/sites/main/blog.py new file mode 100644 index 00000000..3b129ebf --- /dev/null +++ b/sites/main/blog.py @@ -0,0 +1,140 @@ +from collections import namedtuple +from datetime import datetime +import time +import email.utils + +from sphinx.util.compat import Directive +from docutils import nodes + + +class BlogDateDirective(Directive): + """ + Used to parse/attach date info to blog post documents. + + No nodes generated, since none are needed. + """ + has_content = True + + def run(self): + # Tag parent document with parsed date value. + self.state.document.blog_date = datetime.strptime( + self.content[0], "%Y-%m-%d" + ) + # Don't actually insert any nodes, we're already done. + return [] + +class blog_post_list(nodes.General, nodes.Element): + pass + +class BlogPostListDirective(Directive): + """ + Simply spits out a 'blog_post_list' temporary node for replacement. + + Gets replaced at doctree-resolved time - only then will all blog post + documents be written out (& their date directives executed). + """ + def run(self): + return [blog_post_list('')] + + +Post = namedtuple('Post', 'name doc title date opener') + +def get_posts(app): + # Obtain blog posts + post_names = filter(lambda x: x.startswith('blog/'), app.env.found_docs) + posts = map(lambda x: (x, app.env.get_doctree(x)), post_names) + # Obtain common data used for list page & RSS + data = [] + for post, doc in sorted(posts, key=lambda x: x[1].blog_date, reverse=True): + # Welp. No "nice" way to get post title. Thanks Sphinx. + title = doc[0][0][0] + # Date. This may or may not end up reflecting the required + # *input* format, but doing it here gives us flexibility. + date = doc.blog_date + # 1st paragraph as opener. TODO: allow a role or something marking + # where to actually pull from? + opener = doc.traverse(nodes.paragraph)[0] + data.append(Post(post, doc, title, date, opener)) + return data + +def replace_blog_post_lists(app, doctree, fromdocname): + """ + Replace blog_post_list nodes with ordered list-o-links to posts. + """ + # Obtain blog posts + post_names = filter(lambda x: x.startswith('blog/'), app.env.found_docs) + posts = map(lambda x: (x, app.env.get_doctree(x)), post_names) + # Build "list" of links/etc + post_links = [] + for post, doc, title, date, opener in get_posts(app): + # Link itself + uri = app.builder.get_relative_uri(fromdocname, post) + link = nodes.reference('', '', refdocname=post, refuri=uri) + # Title, bolded. TODO: use 'topic' or something maybe? + link.append(nodes.strong('', title)) + date = date.strftime("%Y-%m-%d") + # Meh @ not having great docutils nodes which map to this. + html = '
%s
' % date + timestamp = nodes.raw(text=html, format='html') + # NOTE: may group these within another element later if styling + # necessitates it + group = [timestamp, nodes.paragraph('', '', link), opener] + post_links.extend(group) + + # Replace temp node(s) w/ expanded list-o-links + for node in doctree.traverse(blog_post_list): + node.replace_self(post_links) + +def rss_timestamp(timestamp): + # Use horribly inappropriate module for its magical daylight-savings-aware + # timezone madness. Props to Tinkerer for the idea. + return email.utils.formatdate( + time.mktime(timestamp.timetuple()), + localtime=True + ) + +def generate_rss(app): + # Meh at having to run this subroutine like 3x per build. Not worth trying + # to be clever for now tho. + posts_ = get_posts(app) + # LOL URLs + root = app.config.rss_link + if not root.endswith('/'): + root += '/' + # Oh boy + posts = [ + ( + root + app.builder.get_target_uri(x.name), + x.title, + str(x.opener[0]), # Grab inner text element from paragraph + rss_timestamp(x.date), + ) + for x in posts_ + ] + location = 'blog/rss.xml' + context = { + 'title': app.config.project, + 'link': root, + 'atom': root + location, + 'description': app.config.rss_description, + # 'posts' is sorted by date already + 'date': rss_timestamp(posts_[0].date), + 'posts': posts, + } + yield (location, context, 'rss.xml') + +def setup(app): + # Link in RSS feed back to main website, e.g. 'http://paramiko.org' + app.add_config_value('rss_link', None, '') + # Ditto for RSS description field + app.add_config_value('rss_description', None, '') + # Interprets date metadata in blog post documents + app.add_directive('date', BlogDateDirective) + # Inserts blog post list node (in e.g. a listing page) for replacement + # below + app.add_node(blog_post_list) + app.add_directive('blog-posts', BlogPostListDirective) + # Performs abovementioned replacement + app.connect('doctree-resolved', replace_blog_post_lists) + # Generates RSS page from whole cloth at page generation step + app.connect('html-collect-pages', generate_rss) diff --git a/sites/main/blog.rst b/sites/main/blog.rst new file mode 100644 index 00000000..af9651e4 --- /dev/null +++ b/sites/main/blog.rst @@ -0,0 +1,16 @@ +==== +Blog +==== + +.. blog-posts directive gets replaced with an ordered list of blog posts. + +.. blog-posts:: + + +.. The following toctree ensures blog posts get processed. + +.. toctree:: + :hidden: + :glob: + + blog/* diff --git a/sites/main/blog/first-post.rst b/sites/main/blog/first-post.rst new file mode 100644 index 00000000..7b075073 --- /dev/null +++ b/sites/main/blog/first-post.rst @@ -0,0 +1,7 @@ +=========== +First post! +=========== + +A blog post. + +.. date:: 2013-12-04 diff --git a/sites/main/blog/second-post.rst b/sites/main/blog/second-post.rst new file mode 100644 index 00000000..c4463f33 --- /dev/null +++ b/sites/main/blog/second-post.rst @@ -0,0 +1,7 @@ +=========== +Another one +=========== + +.. date:: 2013-12-05 + +Indeed! diff --git a/sites/main/conf.py b/sites/main/conf.py new file mode 100644 index 00000000..0c7ffe55 --- /dev/null +++ b/sites/main/conf.py @@ -0,0 +1,4 @@ +# Obtain shared config values +import os, sys +sys.path.append(os.path.abspath('..')) +from shared_conf import * diff --git a/sites/main/contact.rst b/sites/main/contact.rst new file mode 100644 index 00000000..b479f170 --- /dev/null +++ b/sites/main/contact.rst @@ -0,0 +1,11 @@ +======= +Contact +======= + +You can get in touch with the developer & user community in any of the +following ways: + +* IRC: ``#paramiko`` on Freenode +* Mailing list: ``paramiko@librelist.com`` (see `the LibreList homepage + `_ for usage details). +* This website's :doc:`blog `. diff --git a/sites/main/contributing.rst b/sites/main/contributing.rst new file mode 100644 index 00000000..b121e64b --- /dev/null +++ b/sites/main/contributing.rst @@ -0,0 +1,19 @@ +============ +Contributing +============ + +How to get the code +=================== + +Our primary Git repository is on Github at `paramiko/paramiko +`; please follow their instruction for +cloning to your local system. (If you intend to submit patches/pull requests, +we recommend forking first, then cloning your fork. Github has excellent +documentation for all this.) + + +How to submit bug reports or new code +===================================== + +Please see `this project-agnostic contribution guide +`_ - we follow it explicitly. diff --git a/sites/main/index.rst b/sites/main/index.rst new file mode 100644 index 00000000..7d203b62 --- /dev/null +++ b/sites/main/index.rst @@ -0,0 +1,31 @@ +Welcome to Paramiko! +==================== + +Paramiko is a Python (2.5+) implementation of the SSHv2 protocol [#]_, +providing both client and server functionality. While it leverages a Python C +extension for low level cryptography (`PyCrypto `_), +Paramiko itself is a pure Python interface around SSH networking concepts. + +This website covers project information for Paramiko such as contribution +guidelines, development roadmap, news/blog, and so forth. Detailed +usage and API documentation can be found at our code documentation site, +`docs.paramiko.org `_. + +.. toctree:: + blog + installing + contributing + contact + + +.. rubric:: Footnotes + +.. [#] + SSH is defined in RFCs + `4251 `_, + `4252 `_, + `4253 `_, and + `4254 `_; + the primary working implementation of the protocol is the `OpenSSH project + `_. Paramiko implements a large portion of the SSH + feature set, but there are occasional gaps. diff --git a/sites/main/installing.rst b/sites/main/installing.rst new file mode 100644 index 00000000..0d4dc1ac --- /dev/null +++ b/sites/main/installing.rst @@ -0,0 +1,105 @@ +========== +Installing +========== + +Paramiko itself +=============== + +The recommended way to get Invoke is to **install the latest stable release** +via `pip `_:: + + $ pip install paramiko + +.. note:: + Users who want the bleeding edge can install the development version via + ``pip install paramiko==dev``. + +We currently support **Python 2.5/2.6/2.7**, with support for Python 3 coming +soon. Users on Python 2.4 or older are urged to upgrade. Paramiko *may* work on +Python 2.4 still, but there is no longer any support guarantee. + +Paramiko has two dependencies: the pure-Python ECDSA module `ecdsa`, and the +PyCrypto C extension. `ecdsa` is easily installable from wherever you +obtained Paramiko's package; PyCrypto may require more work. Read on for +details. + +PyCrypto +======== + +`PyCrypto `_ provides the low-level +(C-based) encryption algorithms we need to implement the SSH protocol. There +are a couple gotchas associated with installing PyCrypto: its compatibility +with Python's package tools, and the fact that it is a C-based extension. + +.. _pycrypto-and-pip: + +Possible gotcha on older Python and/or pip versions +--------------------------------------------------- + +We strongly recommend using ``pip`` to as it is newer and generally better than +``easy_install``. However, a combination of bugs in specific (now rather old) +versions of Python, ``pip`` and PyCrypto can prevent installation of PyCrypto. +Specifically: + +* Python = 2.5.x +* PyCrypto >= 2.1 (required for most modern versions of Paramiko) +* ``pip`` < 0.8.1 + +When all three criteria are met, you may encounter ``No such file or +directory`` IOErrors when trying to ``pip install paramiko`` or ``pip install +PyCrypto``. + +The fix is to make sure at least one of the above criteria is not met, by doing +the following (in order of preference): + +* Upgrade to ``pip`` 0.8.1 or above, e.g. by running ``pip install -U pip``. +* Upgrade to Python 2.6 or above. +* Downgrade to Paramiko 1.7.6 or 1.7.7, which do not require PyCrypto >= 2.1, + and install PyCrypto 2.0.1 (the oldest version on PyPI which works with + Paramiko 1.7.6/1.7.7) + + +C extension +----------- + +Unless you are installing from a precompiled source such as a Debian apt +repository or RedHat RPM, or using :ref:`pypm `, you will also need the +ability to build Python C-based modules from source in order to install +PyCrypto. Users on **Unix-based platforms** such as Ubuntu or Mac OS X will +need the traditional C build toolchain installed (e.g. Developer Tools / XCode +Tools on the Mac, or the ``build-essential`` package on Ubuntu or Debian Linux +-- basically, anything with ``gcc``, ``make`` and so forth) as well as the +Python development libraries, often named ``python-dev`` or similar. + +For **Windows** users we recommend using :ref:`pypm`, installing a C +development environment such as `Cygwin `_ or obtaining a +precompiled Win32 PyCrypto package from `voidspace's Python modules page +`_. + +.. note:: + Some Windows users whose Python is 64-bit have found that the PyCrypto + dependency ``winrandom`` may not install properly, leading to ImportErrors. + In this scenario, you'll probably need to compile ``winrandom`` yourself + via e.g. MS Visual Studio. See `Fabric #194 + `_ for info. + + +.. _pypm: + +ActivePython and PyPM +===================== + +Windows users who already have ActiveState's `ActivePython +`_ distribution installed +may find Paramiko is best installed with `its package manager, PyPM +`_. Below is example output from an +installation of Paramiko via ``pypm``:: + + C:\> pypm install paramiko + The following packages will be installed into "%APPDATA%\Python" (2.7): + paramiko-1.7.8 pycrypto-2.4 + Get: [pypm-free.activestate.com] paramiko 1.7.8 + Get: [pypm-free.activestate.com] pycrypto 2.4 + Installing paramiko-1.7.8 + Installing pycrypto-2.4 + C:\> diff --git a/sites/shared_conf.py b/sites/shared_conf.py new file mode 100644 index 00000000..333db542 --- /dev/null +++ b/sites/shared_conf.py @@ -0,0 +1,56 @@ +from datetime import datetime +import os +import sys + +import alabaster + + +# Add local blog extension +sys.path.append(os.path.abspath('.')) +extensions = ['blog'] +rss_link = 'http://paramiko.org' +rss_description = 'Paramiko project news' + +# Alabaster theme +html_theme_path = [alabaster.get_path()] +# Paths relative to invoking conf.py - not this shared file +html_static_path = ['../_shared_static'] +html_theme = 'alabaster' +html_theme_options = { + 'logo': 'logo.png', + 'logo_name': 'true', + 'description': "A Python implementation of SSHv2.", + 'github_user': 'paramiko', + 'github_repo': 'paramiko', + 'gittip_user': 'bitprophet', + 'analytics_id': 'UA-18486793-2', + + 'link': '#3782BE', + 'link_hover': '#3782BE', + +} +html_sidebars = { + # Landing page (no ToC) + 'index': [ + 'about.html', + 'searchbox.html', + 'donate.html', + ], + # Inner pages get a ToC + '**': [ + 'about.html', + 'localtoc.html', + 'searchbox.html', + 'donate.html', + ] +} + +# Regular settings +project = u'Paramiko' +year = datetime.now().year +copyright = u'%d Jeff Forcier, 2003-2012 Robey Pointer' % year +master_doc = 'index' +templates_path = ['_templates'] +exclude_trees = ['_build'] +source_suffix = '.rst' +default_role = 'obj' diff --git a/tasks.py b/tasks.py index d470dab0..e8cbd3ee 100644 --- a/tasks.py +++ b/tasks.py @@ -6,15 +6,15 @@ from invocations import docs, testing api = Collection.from_module(docs) # TODO: maybe allow rolling configuration into it too heh api.configure({ - 'sphinx.source': 'api', - 'sphinx.target': 'api/_build', + 'sphinx.source': 'sites/docs', + 'sphinx.target': 'sites/docs/_build', }) -api.name = 'api' -site = Collection.from_module(docs) -site.name = 'site' -site.configure({ - 'sphinx.source': 'site', - 'sphinx.target': 'site/_build', +api.name = 'docs' +main = Collection.from_module(docs) +main.name = 'main' +main.configure({ + 'sphinx.source': 'sites/main', + 'sphinx.target': 'sites/main/_build', }) -ns = Collection(testing.test, api=api, site=site) +ns = Collection(testing.test, docs=api, main=main) -- cgit v1.2.3 From c224fdecf174077f3b7a15f056e65b10282fed38 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Mon, 13 Jan 2014 16:16:30 -0800 Subject: Use new behavior from newer Invoke --- tasks.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tasks.py b/tasks.py index e8cbd3ee..3326a773 100644 --- a/tasks.py +++ b/tasks.py @@ -2,17 +2,13 @@ from invoke import Collection from invocations import docs, testing -# TODO: let from_module specify new name -api = Collection.from_module(docs) -# TODO: maybe allow rolling configuration into it too heh -api.configure({ +# Usage doc/API site +api = Collection.from_module(docs, name='docs', config={ 'sphinx.source': 'sites/docs', 'sphinx.target': 'sites/docs/_build', }) -api.name = 'docs' -main = Collection.from_module(docs) -main.name = 'main' -main.configure({ +# Main/about/changelog site +main = Collection.from_module(docs, name='main', config={ 'sphinx.source': 'sites/main', 'sphinx.target': 'sites/main/_build', }) -- cgit v1.2.3 From 2da914252064af8dc419b49a423ab57fdb0617c4 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Tue, 21 Jan 2014 16:59:21 -0800 Subject: Rename 'main' doctree to 'www'; refactor sphinx task conf --- sites/main/_templates/rss.xml | 19 ------ sites/main/blog.py | 140 ---------------------------------------- sites/main/blog.rst | 16 ----- sites/main/blog/first-post.rst | 7 -- sites/main/blog/second-post.rst | 7 -- sites/main/conf.py | 4 -- sites/main/contact.rst | 11 ---- sites/main/contributing.rst | 19 ------ sites/main/index.rst | 31 --------- sites/main/installing.rst | 105 ------------------------------ sites/www/_templates/rss.xml | 19 ++++++ sites/www/blog.py | 140 ++++++++++++++++++++++++++++++++++++++++ sites/www/blog.rst | 16 +++++ sites/www/blog/first-post.rst | 7 ++ sites/www/blog/second-post.rst | 7 ++ sites/www/conf.py | 4 ++ sites/www/contact.rst | 11 ++++ sites/www/contributing.rst | 19 ++++++ sites/www/index.rst | 31 +++++++++ sites/www/installing.rst | 105 ++++++++++++++++++++++++++++++ tasks.py | 27 +++++--- 21 files changed, 376 insertions(+), 369 deletions(-) delete mode 100644 sites/main/_templates/rss.xml delete mode 100644 sites/main/blog.py delete mode 100644 sites/main/blog.rst delete mode 100644 sites/main/blog/first-post.rst delete mode 100644 sites/main/blog/second-post.rst delete mode 100644 sites/main/conf.py delete mode 100644 sites/main/contact.rst delete mode 100644 sites/main/contributing.rst delete mode 100644 sites/main/index.rst delete mode 100644 sites/main/installing.rst create mode 100644 sites/www/_templates/rss.xml create mode 100644 sites/www/blog.py create mode 100644 sites/www/blog.rst create mode 100644 sites/www/blog/first-post.rst create mode 100644 sites/www/blog/second-post.rst create mode 100644 sites/www/conf.py create mode 100644 sites/www/contact.rst create mode 100644 sites/www/contributing.rst create mode 100644 sites/www/index.rst create mode 100644 sites/www/installing.rst diff --git a/sites/main/_templates/rss.xml b/sites/main/_templates/rss.xml deleted file mode 100644 index f6f9cbd1..00000000 --- a/sites/main/_templates/rss.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - {{ title }} - {{ link }} - {{ description }} - {{ date }} - {% for link, title, desc, date in posts %} - - {{ link }} - {{ link }} - <![CDATA[{{ title }}]]> - - {{ date }} - - {% endfor %} - - diff --git a/sites/main/blog.py b/sites/main/blog.py deleted file mode 100644 index 3b129ebf..00000000 --- a/sites/main/blog.py +++ /dev/null @@ -1,140 +0,0 @@ -from collections import namedtuple -from datetime import datetime -import time -import email.utils - -from sphinx.util.compat import Directive -from docutils import nodes - - -class BlogDateDirective(Directive): - """ - Used to parse/attach date info to blog post documents. - - No nodes generated, since none are needed. - """ - has_content = True - - def run(self): - # Tag parent document with parsed date value. - self.state.document.blog_date = datetime.strptime( - self.content[0], "%Y-%m-%d" - ) - # Don't actually insert any nodes, we're already done. - return [] - -class blog_post_list(nodes.General, nodes.Element): - pass - -class BlogPostListDirective(Directive): - """ - Simply spits out a 'blog_post_list' temporary node for replacement. - - Gets replaced at doctree-resolved time - only then will all blog post - documents be written out (& their date directives executed). - """ - def run(self): - return [blog_post_list('')] - - -Post = namedtuple('Post', 'name doc title date opener') - -def get_posts(app): - # Obtain blog posts - post_names = filter(lambda x: x.startswith('blog/'), app.env.found_docs) - posts = map(lambda x: (x, app.env.get_doctree(x)), post_names) - # Obtain common data used for list page & RSS - data = [] - for post, doc in sorted(posts, key=lambda x: x[1].blog_date, reverse=True): - # Welp. No "nice" way to get post title. Thanks Sphinx. - title = doc[0][0][0] - # Date. This may or may not end up reflecting the required - # *input* format, but doing it here gives us flexibility. - date = doc.blog_date - # 1st paragraph as opener. TODO: allow a role or something marking - # where to actually pull from? - opener = doc.traverse(nodes.paragraph)[0] - data.append(Post(post, doc, title, date, opener)) - return data - -def replace_blog_post_lists(app, doctree, fromdocname): - """ - Replace blog_post_list nodes with ordered list-o-links to posts. - """ - # Obtain blog posts - post_names = filter(lambda x: x.startswith('blog/'), app.env.found_docs) - posts = map(lambda x: (x, app.env.get_doctree(x)), post_names) - # Build "list" of links/etc - post_links = [] - for post, doc, title, date, opener in get_posts(app): - # Link itself - uri = app.builder.get_relative_uri(fromdocname, post) - link = nodes.reference('', '', refdocname=post, refuri=uri) - # Title, bolded. TODO: use 'topic' or something maybe? - link.append(nodes.strong('', title)) - date = date.strftime("%Y-%m-%d") - # Meh @ not having great docutils nodes which map to this. - html = '
%s
' % date - timestamp = nodes.raw(text=html, format='html') - # NOTE: may group these within another element later if styling - # necessitates it - group = [timestamp, nodes.paragraph('', '', link), opener] - post_links.extend(group) - - # Replace temp node(s) w/ expanded list-o-links - for node in doctree.traverse(blog_post_list): - node.replace_self(post_links) - -def rss_timestamp(timestamp): - # Use horribly inappropriate module for its magical daylight-savings-aware - # timezone madness. Props to Tinkerer for the idea. - return email.utils.formatdate( - time.mktime(timestamp.timetuple()), - localtime=True - ) - -def generate_rss(app): - # Meh at having to run this subroutine like 3x per build. Not worth trying - # to be clever for now tho. - posts_ = get_posts(app) - # LOL URLs - root = app.config.rss_link - if not root.endswith('/'): - root += '/' - # Oh boy - posts = [ - ( - root + app.builder.get_target_uri(x.name), - x.title, - str(x.opener[0]), # Grab inner text element from paragraph - rss_timestamp(x.date), - ) - for x in posts_ - ] - location = 'blog/rss.xml' - context = { - 'title': app.config.project, - 'link': root, - 'atom': root + location, - 'description': app.config.rss_description, - # 'posts' is sorted by date already - 'date': rss_timestamp(posts_[0].date), - 'posts': posts, - } - yield (location, context, 'rss.xml') - -def setup(app): - # Link in RSS feed back to main website, e.g. 'http://paramiko.org' - app.add_config_value('rss_link', None, '') - # Ditto for RSS description field - app.add_config_value('rss_description', None, '') - # Interprets date metadata in blog post documents - app.add_directive('date', BlogDateDirective) - # Inserts blog post list node (in e.g. a listing page) for replacement - # below - app.add_node(blog_post_list) - app.add_directive('blog-posts', BlogPostListDirective) - # Performs abovementioned replacement - app.connect('doctree-resolved', replace_blog_post_lists) - # Generates RSS page from whole cloth at page generation step - app.connect('html-collect-pages', generate_rss) diff --git a/sites/main/blog.rst b/sites/main/blog.rst deleted file mode 100644 index af9651e4..00000000 --- a/sites/main/blog.rst +++ /dev/null @@ -1,16 +0,0 @@ -==== -Blog -==== - -.. blog-posts directive gets replaced with an ordered list of blog posts. - -.. blog-posts:: - - -.. The following toctree ensures blog posts get processed. - -.. toctree:: - :hidden: - :glob: - - blog/* diff --git a/sites/main/blog/first-post.rst b/sites/main/blog/first-post.rst deleted file mode 100644 index 7b075073..00000000 --- a/sites/main/blog/first-post.rst +++ /dev/null @@ -1,7 +0,0 @@ -=========== -First post! -=========== - -A blog post. - -.. date:: 2013-12-04 diff --git a/sites/main/blog/second-post.rst b/sites/main/blog/second-post.rst deleted file mode 100644 index c4463f33..00000000 --- a/sites/main/blog/second-post.rst +++ /dev/null @@ -1,7 +0,0 @@ -=========== -Another one -=========== - -.. date:: 2013-12-05 - -Indeed! diff --git a/sites/main/conf.py b/sites/main/conf.py deleted file mode 100644 index 0c7ffe55..00000000 --- a/sites/main/conf.py +++ /dev/null @@ -1,4 +0,0 @@ -# Obtain shared config values -import os, sys -sys.path.append(os.path.abspath('..')) -from shared_conf import * diff --git a/sites/main/contact.rst b/sites/main/contact.rst deleted file mode 100644 index b479f170..00000000 --- a/sites/main/contact.rst +++ /dev/null @@ -1,11 +0,0 @@ -======= -Contact -======= - -You can get in touch with the developer & user community in any of the -following ways: - -* IRC: ``#paramiko`` on Freenode -* Mailing list: ``paramiko@librelist.com`` (see `the LibreList homepage - `_ for usage details). -* This website's :doc:`blog `. diff --git a/sites/main/contributing.rst b/sites/main/contributing.rst deleted file mode 100644 index b121e64b..00000000 --- a/sites/main/contributing.rst +++ /dev/null @@ -1,19 +0,0 @@ -============ -Contributing -============ - -How to get the code -=================== - -Our primary Git repository is on Github at `paramiko/paramiko -`; please follow their instruction for -cloning to your local system. (If you intend to submit patches/pull requests, -we recommend forking first, then cloning your fork. Github has excellent -documentation for all this.) - - -How to submit bug reports or new code -===================================== - -Please see `this project-agnostic contribution guide -`_ - we follow it explicitly. diff --git a/sites/main/index.rst b/sites/main/index.rst deleted file mode 100644 index 7d203b62..00000000 --- a/sites/main/index.rst +++ /dev/null @@ -1,31 +0,0 @@ -Welcome to Paramiko! -==================== - -Paramiko is a Python (2.5+) implementation of the SSHv2 protocol [#]_, -providing both client and server functionality. While it leverages a Python C -extension for low level cryptography (`PyCrypto `_), -Paramiko itself is a pure Python interface around SSH networking concepts. - -This website covers project information for Paramiko such as contribution -guidelines, development roadmap, news/blog, and so forth. Detailed -usage and API documentation can be found at our code documentation site, -`docs.paramiko.org `_. - -.. toctree:: - blog - installing - contributing - contact - - -.. rubric:: Footnotes - -.. [#] - SSH is defined in RFCs - `4251 `_, - `4252 `_, - `4253 `_, and - `4254 `_; - the primary working implementation of the protocol is the `OpenSSH project - `_. Paramiko implements a large portion of the SSH - feature set, but there are occasional gaps. diff --git a/sites/main/installing.rst b/sites/main/installing.rst deleted file mode 100644 index 0d4dc1ac..00000000 --- a/sites/main/installing.rst +++ /dev/null @@ -1,105 +0,0 @@ -========== -Installing -========== - -Paramiko itself -=============== - -The recommended way to get Invoke is to **install the latest stable release** -via `pip `_:: - - $ pip install paramiko - -.. note:: - Users who want the bleeding edge can install the development version via - ``pip install paramiko==dev``. - -We currently support **Python 2.5/2.6/2.7**, with support for Python 3 coming -soon. Users on Python 2.4 or older are urged to upgrade. Paramiko *may* work on -Python 2.4 still, but there is no longer any support guarantee. - -Paramiko has two dependencies: the pure-Python ECDSA module `ecdsa`, and the -PyCrypto C extension. `ecdsa` is easily installable from wherever you -obtained Paramiko's package; PyCrypto may require more work. Read on for -details. - -PyCrypto -======== - -`PyCrypto `_ provides the low-level -(C-based) encryption algorithms we need to implement the SSH protocol. There -are a couple gotchas associated with installing PyCrypto: its compatibility -with Python's package tools, and the fact that it is a C-based extension. - -.. _pycrypto-and-pip: - -Possible gotcha on older Python and/or pip versions ---------------------------------------------------- - -We strongly recommend using ``pip`` to as it is newer and generally better than -``easy_install``. However, a combination of bugs in specific (now rather old) -versions of Python, ``pip`` and PyCrypto can prevent installation of PyCrypto. -Specifically: - -* Python = 2.5.x -* PyCrypto >= 2.1 (required for most modern versions of Paramiko) -* ``pip`` < 0.8.1 - -When all three criteria are met, you may encounter ``No such file or -directory`` IOErrors when trying to ``pip install paramiko`` or ``pip install -PyCrypto``. - -The fix is to make sure at least one of the above criteria is not met, by doing -the following (in order of preference): - -* Upgrade to ``pip`` 0.8.1 or above, e.g. by running ``pip install -U pip``. -* Upgrade to Python 2.6 or above. -* Downgrade to Paramiko 1.7.6 or 1.7.7, which do not require PyCrypto >= 2.1, - and install PyCrypto 2.0.1 (the oldest version on PyPI which works with - Paramiko 1.7.6/1.7.7) - - -C extension ------------ - -Unless you are installing from a precompiled source such as a Debian apt -repository or RedHat RPM, or using :ref:`pypm `, you will also need the -ability to build Python C-based modules from source in order to install -PyCrypto. Users on **Unix-based platforms** such as Ubuntu or Mac OS X will -need the traditional C build toolchain installed (e.g. Developer Tools / XCode -Tools on the Mac, or the ``build-essential`` package on Ubuntu or Debian Linux --- basically, anything with ``gcc``, ``make`` and so forth) as well as the -Python development libraries, often named ``python-dev`` or similar. - -For **Windows** users we recommend using :ref:`pypm`, installing a C -development environment such as `Cygwin `_ or obtaining a -precompiled Win32 PyCrypto package from `voidspace's Python modules page -`_. - -.. note:: - Some Windows users whose Python is 64-bit have found that the PyCrypto - dependency ``winrandom`` may not install properly, leading to ImportErrors. - In this scenario, you'll probably need to compile ``winrandom`` yourself - via e.g. MS Visual Studio. See `Fabric #194 - `_ for info. - - -.. _pypm: - -ActivePython and PyPM -===================== - -Windows users who already have ActiveState's `ActivePython -`_ distribution installed -may find Paramiko is best installed with `its package manager, PyPM -`_. Below is example output from an -installation of Paramiko via ``pypm``:: - - C:\> pypm install paramiko - The following packages will be installed into "%APPDATA%\Python" (2.7): - paramiko-1.7.8 pycrypto-2.4 - Get: [pypm-free.activestate.com] paramiko 1.7.8 - Get: [pypm-free.activestate.com] pycrypto 2.4 - Installing paramiko-1.7.8 - Installing pycrypto-2.4 - C:\> diff --git a/sites/www/_templates/rss.xml b/sites/www/_templates/rss.xml new file mode 100644 index 00000000..f6f9cbd1 --- /dev/null +++ b/sites/www/_templates/rss.xml @@ -0,0 +1,19 @@ + + + + + {{ title }} + {{ link }} + {{ description }} + {{ date }} + {% for link, title, desc, date in posts %} + + {{ link }} + {{ link }} + <![CDATA[{{ title }}]]> + + {{ date }} + + {% endfor %} + + diff --git a/sites/www/blog.py b/sites/www/blog.py new file mode 100644 index 00000000..3b129ebf --- /dev/null +++ b/sites/www/blog.py @@ -0,0 +1,140 @@ +from collections import namedtuple +from datetime import datetime +import time +import email.utils + +from sphinx.util.compat import Directive +from docutils import nodes + + +class BlogDateDirective(Directive): + """ + Used to parse/attach date info to blog post documents. + + No nodes generated, since none are needed. + """ + has_content = True + + def run(self): + # Tag parent document with parsed date value. + self.state.document.blog_date = datetime.strptime( + self.content[0], "%Y-%m-%d" + ) + # Don't actually insert any nodes, we're already done. + return [] + +class blog_post_list(nodes.General, nodes.Element): + pass + +class BlogPostListDirective(Directive): + """ + Simply spits out a 'blog_post_list' temporary node for replacement. + + Gets replaced at doctree-resolved time - only then will all blog post + documents be written out (& their date directives executed). + """ + def run(self): + return [blog_post_list('')] + + +Post = namedtuple('Post', 'name doc title date opener') + +def get_posts(app): + # Obtain blog posts + post_names = filter(lambda x: x.startswith('blog/'), app.env.found_docs) + posts = map(lambda x: (x, app.env.get_doctree(x)), post_names) + # Obtain common data used for list page & RSS + data = [] + for post, doc in sorted(posts, key=lambda x: x[1].blog_date, reverse=True): + # Welp. No "nice" way to get post title. Thanks Sphinx. + title = doc[0][0][0] + # Date. This may or may not end up reflecting the required + # *input* format, but doing it here gives us flexibility. + date = doc.blog_date + # 1st paragraph as opener. TODO: allow a role or something marking + # where to actually pull from? + opener = doc.traverse(nodes.paragraph)[0] + data.append(Post(post, doc, title, date, opener)) + return data + +def replace_blog_post_lists(app, doctree, fromdocname): + """ + Replace blog_post_list nodes with ordered list-o-links to posts. + """ + # Obtain blog posts + post_names = filter(lambda x: x.startswith('blog/'), app.env.found_docs) + posts = map(lambda x: (x, app.env.get_doctree(x)), post_names) + # Build "list" of links/etc + post_links = [] + for post, doc, title, date, opener in get_posts(app): + # Link itself + uri = app.builder.get_relative_uri(fromdocname, post) + link = nodes.reference('', '', refdocname=post, refuri=uri) + # Title, bolded. TODO: use 'topic' or something maybe? + link.append(nodes.strong('', title)) + date = date.strftime("%Y-%m-%d") + # Meh @ not having great docutils nodes which map to this. + html = '
%s
' % date + timestamp = nodes.raw(text=html, format='html') + # NOTE: may group these within another element later if styling + # necessitates it + group = [timestamp, nodes.paragraph('', '', link), opener] + post_links.extend(group) + + # Replace temp node(s) w/ expanded list-o-links + for node in doctree.traverse(blog_post_list): + node.replace_self(post_links) + +def rss_timestamp(timestamp): + # Use horribly inappropriate module for its magical daylight-savings-aware + # timezone madness. Props to Tinkerer for the idea. + return email.utils.formatdate( + time.mktime(timestamp.timetuple()), + localtime=True + ) + +def generate_rss(app): + # Meh at having to run this subroutine like 3x per build. Not worth trying + # to be clever for now tho. + posts_ = get_posts(app) + # LOL URLs + root = app.config.rss_link + if not root.endswith('/'): + root += '/' + # Oh boy + posts = [ + ( + root + app.builder.get_target_uri(x.name), + x.title, + str(x.opener[0]), # Grab inner text element from paragraph + rss_timestamp(x.date), + ) + for x in posts_ + ] + location = 'blog/rss.xml' + context = { + 'title': app.config.project, + 'link': root, + 'atom': root + location, + 'description': app.config.rss_description, + # 'posts' is sorted by date already + 'date': rss_timestamp(posts_[0].date), + 'posts': posts, + } + yield (location, context, 'rss.xml') + +def setup(app): + # Link in RSS feed back to main website, e.g. 'http://paramiko.org' + app.add_config_value('rss_link', None, '') + # Ditto for RSS description field + app.add_config_value('rss_description', None, '') + # Interprets date metadata in blog post documents + app.add_directive('date', BlogDateDirective) + # Inserts blog post list node (in e.g. a listing page) for replacement + # below + app.add_node(blog_post_list) + app.add_directive('blog-posts', BlogPostListDirective) + # Performs abovementioned replacement + app.connect('doctree-resolved', replace_blog_post_lists) + # Generates RSS page from whole cloth at page generation step + app.connect('html-collect-pages', generate_rss) diff --git a/sites/www/blog.rst b/sites/www/blog.rst new file mode 100644 index 00000000..af9651e4 --- /dev/null +++ b/sites/www/blog.rst @@ -0,0 +1,16 @@ +==== +Blog +==== + +.. blog-posts directive gets replaced with an ordered list of blog posts. + +.. blog-posts:: + + +.. The following toctree ensures blog posts get processed. + +.. toctree:: + :hidden: + :glob: + + blog/* diff --git a/sites/www/blog/first-post.rst b/sites/www/blog/first-post.rst new file mode 100644 index 00000000..7b075073 --- /dev/null +++ b/sites/www/blog/first-post.rst @@ -0,0 +1,7 @@ +=========== +First post! +=========== + +A blog post. + +.. date:: 2013-12-04 diff --git a/sites/www/blog/second-post.rst b/sites/www/blog/second-post.rst new file mode 100644 index 00000000..c4463f33 --- /dev/null +++ b/sites/www/blog/second-post.rst @@ -0,0 +1,7 @@ +=========== +Another one +=========== + +.. date:: 2013-12-05 + +Indeed! diff --git a/sites/www/conf.py b/sites/www/conf.py new file mode 100644 index 00000000..0c7ffe55 --- /dev/null +++ b/sites/www/conf.py @@ -0,0 +1,4 @@ +# Obtain shared config values +import os, sys +sys.path.append(os.path.abspath('..')) +from shared_conf import * diff --git a/sites/www/contact.rst b/sites/www/contact.rst new file mode 100644 index 00000000..b479f170 --- /dev/null +++ b/sites/www/contact.rst @@ -0,0 +1,11 @@ +======= +Contact +======= + +You can get in touch with the developer & user community in any of the +following ways: + +* IRC: ``#paramiko`` on Freenode +* Mailing list: ``paramiko@librelist.com`` (see `the LibreList homepage + `_ for usage details). +* This website's :doc:`blog `. diff --git a/sites/www/contributing.rst b/sites/www/contributing.rst new file mode 100644 index 00000000..b121e64b --- /dev/null +++ b/sites/www/contributing.rst @@ -0,0 +1,19 @@ +============ +Contributing +============ + +How to get the code +=================== + +Our primary Git repository is on Github at `paramiko/paramiko +`; please follow their instruction for +cloning to your local system. (If you intend to submit patches/pull requests, +we recommend forking first, then cloning your fork. Github has excellent +documentation for all this.) + + +How to submit bug reports or new code +===================================== + +Please see `this project-agnostic contribution guide +`_ - we follow it explicitly. diff --git a/sites/www/index.rst b/sites/www/index.rst new file mode 100644 index 00000000..7d203b62 --- /dev/null +++ b/sites/www/index.rst @@ -0,0 +1,31 @@ +Welcome to Paramiko! +==================== + +Paramiko is a Python (2.5+) implementation of the SSHv2 protocol [#]_, +providing both client and server functionality. While it leverages a Python C +extension for low level cryptography (`PyCrypto `_), +Paramiko itself is a pure Python interface around SSH networking concepts. + +This website covers project information for Paramiko such as contribution +guidelines, development roadmap, news/blog, and so forth. Detailed +usage and API documentation can be found at our code documentation site, +`docs.paramiko.org `_. + +.. toctree:: + blog + installing + contributing + contact + + +.. rubric:: Footnotes + +.. [#] + SSH is defined in RFCs + `4251 `_, + `4252 `_, + `4253 `_, and + `4254 `_; + the primary working implementation of the protocol is the `OpenSSH project + `_. Paramiko implements a large portion of the SSH + feature set, but there are occasional gaps. diff --git a/sites/www/installing.rst b/sites/www/installing.rst new file mode 100644 index 00000000..0d4dc1ac --- /dev/null +++ b/sites/www/installing.rst @@ -0,0 +1,105 @@ +========== +Installing +========== + +Paramiko itself +=============== + +The recommended way to get Invoke is to **install the latest stable release** +via `pip `_:: + + $ pip install paramiko + +.. note:: + Users who want the bleeding edge can install the development version via + ``pip install paramiko==dev``. + +We currently support **Python 2.5/2.6/2.7**, with support for Python 3 coming +soon. Users on Python 2.4 or older are urged to upgrade. Paramiko *may* work on +Python 2.4 still, but there is no longer any support guarantee. + +Paramiko has two dependencies: the pure-Python ECDSA module `ecdsa`, and the +PyCrypto C extension. `ecdsa` is easily installable from wherever you +obtained Paramiko's package; PyCrypto may require more work. Read on for +details. + +PyCrypto +======== + +`PyCrypto `_ provides the low-level +(C-based) encryption algorithms we need to implement the SSH protocol. There +are a couple gotchas associated with installing PyCrypto: its compatibility +with Python's package tools, and the fact that it is a C-based extension. + +.. _pycrypto-and-pip: + +Possible gotcha on older Python and/or pip versions +--------------------------------------------------- + +We strongly recommend using ``pip`` to as it is newer and generally better than +``easy_install``. However, a combination of bugs in specific (now rather old) +versions of Python, ``pip`` and PyCrypto can prevent installation of PyCrypto. +Specifically: + +* Python = 2.5.x +* PyCrypto >= 2.1 (required for most modern versions of Paramiko) +* ``pip`` < 0.8.1 + +When all three criteria are met, you may encounter ``No such file or +directory`` IOErrors when trying to ``pip install paramiko`` or ``pip install +PyCrypto``. + +The fix is to make sure at least one of the above criteria is not met, by doing +the following (in order of preference): + +* Upgrade to ``pip`` 0.8.1 or above, e.g. by running ``pip install -U pip``. +* Upgrade to Python 2.6 or above. +* Downgrade to Paramiko 1.7.6 or 1.7.7, which do not require PyCrypto >= 2.1, + and install PyCrypto 2.0.1 (the oldest version on PyPI which works with + Paramiko 1.7.6/1.7.7) + + +C extension +----------- + +Unless you are installing from a precompiled source such as a Debian apt +repository or RedHat RPM, or using :ref:`pypm `, you will also need the +ability to build Python C-based modules from source in order to install +PyCrypto. Users on **Unix-based platforms** such as Ubuntu or Mac OS X will +need the traditional C build toolchain installed (e.g. Developer Tools / XCode +Tools on the Mac, or the ``build-essential`` package on Ubuntu or Debian Linux +-- basically, anything with ``gcc``, ``make`` and so forth) as well as the +Python development libraries, often named ``python-dev`` or similar. + +For **Windows** users we recommend using :ref:`pypm`, installing a C +development environment such as `Cygwin `_ or obtaining a +precompiled Win32 PyCrypto package from `voidspace's Python modules page +`_. + +.. note:: + Some Windows users whose Python is 64-bit have found that the PyCrypto + dependency ``winrandom`` may not install properly, leading to ImportErrors. + In this scenario, you'll probably need to compile ``winrandom`` yourself + via e.g. MS Visual Studio. See `Fabric #194 + `_ for info. + + +.. _pypm: + +ActivePython and PyPM +===================== + +Windows users who already have ActiveState's `ActivePython +`_ distribution installed +may find Paramiko is best installed with `its package manager, PyPM +`_. Below is example output from an +installation of Paramiko via ``pypm``:: + + C:\> pypm install paramiko + The following packages will be installed into "%APPDATA%\Python" (2.7): + paramiko-1.7.8 pycrypto-2.4 + Get: [pypm-free.activestate.com] paramiko 1.7.8 + Get: [pypm-free.activestate.com] pycrypto 2.4 + Installing paramiko-1.7.8 + Installing pycrypto-2.4 + C:\> diff --git a/tasks.py b/tasks.py index 3326a773..c7164158 100644 --- a/tasks.py +++ b/tasks.py @@ -1,16 +1,23 @@ +from os.path import join + from invoke import Collection -from invocations import docs, testing +from invocations import docs as _docs, testing + +d = 'sites' -# Usage doc/API site -api = Collection.from_module(docs, name='docs', config={ - 'sphinx.source': 'sites/docs', - 'sphinx.target': 'sites/docs/_build', +# Usage doc/API site (published as docs.paramiko.org) +path = join(d, 'docs') +docs = Collection.from_module(_docs, name='docs', config={ + 'sphinx.source': path, + 'sphinx.target': join(path, '_build'), }) -# Main/about/changelog site -main = Collection.from_module(docs, name='main', config={ - 'sphinx.source': 'sites/main', - 'sphinx.target': 'sites/main/_build', + +# Main/about/changelog site ((www.)?paramiko.org) +path = join(d, 'www') +www = Collection.from_module(_docs, name='www', config={ + 'sphinx.source': path, + 'sphinx.target': join(path, '_build'), }) -ns = Collection(testing.test, docs=api, main=main) +ns = Collection(testing.test, docs=docs, www=www) -- cgit v1.2.3 From 5a1f927310414ca47408c3f2f81a0b43beb8cb19 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Wed, 22 Jan 2014 10:55:39 -0800 Subject: Blog only used/exists in www, don't import it in docs site --- sites/shared_conf.py | 6 ------ sites/www/conf.py | 7 +++++++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sites/shared_conf.py b/sites/shared_conf.py index 333db542..89e0a56d 100644 --- a/sites/shared_conf.py +++ b/sites/shared_conf.py @@ -5,12 +5,6 @@ import sys import alabaster -# Add local blog extension -sys.path.append(os.path.abspath('.')) -extensions = ['blog'] -rss_link = 'http://paramiko.org' -rss_description = 'Paramiko project news' - # Alabaster theme html_theme_path = [alabaster.get_path()] # Paths relative to invoking conf.py - not this shared file diff --git a/sites/www/conf.py b/sites/www/conf.py index 0c7ffe55..e504ec7b 100644 --- a/sites/www/conf.py +++ b/sites/www/conf.py @@ -2,3 +2,10 @@ import os, sys sys.path.append(os.path.abspath('..')) from shared_conf import * + +# Add local blog extension +sys.path.append(os.path.abspath('.')) +extensions = ['blog'] +rss_link = 'http://paramiko.org' +rss_description = 'Paramiko project news' + -- cgit v1.2.3 From 03768eadcafbbab93f9c5c6c67479e97249e7a09 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Wed, 22 Jan 2014 12:48:32 -0800 Subject: Migrate 1.10.x NEWS entries to Sphinx changelog --- dev-requirements.txt | 1 + sites/www/changelog.rst | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ sites/www/conf.py | 4 +++ sites/www/index.rst | 5 ++-- 4 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 sites/www/changelog.rst diff --git a/dev-requirements.txt b/dev-requirements.txt index 59a1f144..a2b9a4e8 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -4,3 +4,4 @@ invoke>=0.6.1 invocations>=0.4.4 sphinx>=1.1.3 alabaster>=0.1.0 +releases>=0.2.4 diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst new file mode 100644 index 00000000..d83de54b --- /dev/null +++ b/sites/www/changelog.rst @@ -0,0 +1,77 @@ +========= +Changelog +========= + +* :release:`1.10.6 <2014-01-21>` +* :bug:`193` (and its attentant PRs :issue:`230` & :issue:`253`): Fix SSH agent + problems present on Windows. Thanks to David Hobbs for initial report and to + Aarni Koskela & Olle Lundberg for the patches. +* :release:`1.10.5 <2014-01-08>` +* :bug:`176`: Fix AttributeError bugs in known_hosts file (re)loading. Thanks + to Nathan Scowcroft for the patch & Martin Blumenstingl for the initial test + case. +* :release:`1.10.4 <2013-09-27>` +* :bug:`179`: Fix a missing variable causing errors when an ssh_config file has + a non-default AddressFamily set. Thanks to Ed Marshall & Tomaz Muraus for + catch & patch. +* :bug:`200`: Fix an exception-causing typo in `demo_simple.py`. Thanks to Alex + Buchanan for catch & Dave Foster for patch. +* :bug:`199`: Typo fix in the license header cross-project. Thanks to Armin + Ronacher for catch & patch. +* :release:`1.10.3 <2013-09-20>` +* :bug:`162`: Clean up HMAC module import to avoid deadlocks in certain uses of + SSHClient. Thanks to Gernot Hillier for the catch & suggested fix. +* :bug:`36`: Fix the port-forwarding demo to avoid file descriptor errors. + Thanks to Jonathan Halcrow for catch & patch. +* :bug:`168`: Update config handling to properly handle multiple 'localforward' + and 'remoteforward' keys. Thanks to Emre Yılmaz for the patch. +* :release:`1.10.2 <2013-07-26>` +* :bug:`153`, :issue:`67`: Warn on parse failure when reading known_hosts + file. Thanks to `@glasserc` for patch. +* :bug:`146`: Indentation fixes for readability. Thanks to Abhinav Upadhyay for + catch & patch. +* :release:`1.10.1 <2013-04-05>` +* :bug:`142`: (`Fabric #811 `_) + SFTP put of empty file will still return the attributes of the put file. + Thanks to Jason R. Coombs for the patch. +* :bug:`154`: (`Fabric #876 `_) + Forwarded SSH agent connections left stale local pipes lying around, which + could cause local (and sometimes remote or network) resource starvation when + running many agent-using remote commands. Thanks to Kevin Tegtmeier for catch + & patch. +* :release:`1.10.0 <2013-03-01>` +* :feature:`66`: Batch SFTP writes to help speed up file transfers. Thanks to + Olle Lundberg for the patch. +* :bug:`133 major`: Fix handling of window-change events to be on-spec and not + attempt to wait for a response from the remote sshd; this fixes problems with + less common targets such as some Cisco devices. Thanks to Phillip Heller for + catch & patch. +* :feature:`93`: Overhaul SSH config parsing to be in line with `man + ssh_config` (& the behavior of `ssh` itself), including addition of parameter + expansion within config values. Thanks to Olle Lundberg for the patch. +* :feature:`110`: Honor SSH config `AddressFamily` setting when looking up + local host's FQDN. Thanks to John Hensley for the patch. +* :feature:`128`: Defer FQDN resolution until needed, when parsing SSH config + files. Thanks to Parantapa Bhattacharya for catch & patch. +* :bug:`102 major`: Forego random padding for packets when running under + `*-ctr` ciphers. This corrects some slowdowns on platforms where random byte + generation is inefficient (e.g. Windows). Thanks to `@warthog618` for catch + & patch, and Michael van der Kolff for code/technique review. +* :feature:`127`: Turn `SFTPFile` into a context manager. Thanks to Michael + Williamson for the patch. +* :feature:`116`: Limit `Message.get_bytes` to an upper bound of 1MB to protect + against potential DoS vectors. Thanks to `@mvschaik` for catch & patch. +* :feature:`115`: Add convenience `get_pty` kwarg to `Client.exec_command` so + users not manually controlling a channel object can still toggle PTY + creation. Thanks to Michael van der Kolff for the patch. +* :feature:`71`: Add `SFTPClient.putfo` and `.getfo` methods to allow direct + uploading/downloading of file-like objects. Thanks to Eric Buehl for the + patch. +* :feature:`113`: Add `timeout` parameter to `SSHClient.exec_command` for + easier setting of the command's internal channel object's timeout. Thanks to + Cernov Vladimir for the patch. +* :support:`94`: Remove duplication of SSH port constant. Thanks to Olle + Lundberg for the catch. +* :feature:`80`: Expose the internal "is closed" property of the file transfer + class `BufferedFile` as `.closed`, better conforming to Python's file + interface. Thanks to `@smunaut` and James Hiscock for catch & patch. diff --git a/sites/www/conf.py b/sites/www/conf.py index e504ec7b..c144b5b4 100644 --- a/sites/www/conf.py +++ b/sites/www/conf.py @@ -9,3 +9,7 @@ extensions = ['blog'] rss_link = 'http://paramiko.org' rss_description = 'Paramiko project news' +# Add Releases changelog extension +extensions.append('releases') +releases_release_uri = "https://github.com/paramiko/paramiko/tree/%s" +releases_issue_uri = "https://github.com/paramiko/paramiko/issues/%s" diff --git a/sites/www/index.rst b/sites/www/index.rst index 7d203b62..f8db6fd0 100644 --- a/sites/www/index.rst +++ b/sites/www/index.rst @@ -6,13 +6,14 @@ providing both client and server functionality. While it leverages a Python C extension for low level cryptography (`PyCrypto `_), Paramiko itself is a pure Python interface around SSH networking concepts. -This website covers project information for Paramiko such as contribution -guidelines, development roadmap, news/blog, and so forth. Detailed +This website covers project information for Paramiko such as the changelog, +contribution guidelines, development roadmap, news/blog, and so forth. Detailed usage and API documentation can be found at our code documentation site, `docs.paramiko.org `_. .. toctree:: blog + changelog installing contributing contact -- cgit v1.2.3 From dde21a7de09bd92a6a362a26009a56a942b3d246 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Wed, 22 Jan 2014 14:25:08 -0800 Subject: Nuke extraneous colons, add 'major' notes --- sites/www/changelog.rst | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst index d83de54b..bba78949 100644 --- a/sites/www/changelog.rst +++ b/sites/www/changelog.rst @@ -7,71 +7,71 @@ Changelog problems present on Windows. Thanks to David Hobbs for initial report and to Aarni Koskela & Olle Lundberg for the patches. * :release:`1.10.5 <2014-01-08>` -* :bug:`176`: Fix AttributeError bugs in known_hosts file (re)loading. Thanks +* :bug:`176` Fix AttributeError bugs in known_hosts file (re)loading. Thanks to Nathan Scowcroft for the patch & Martin Blumenstingl for the initial test case. * :release:`1.10.4 <2013-09-27>` -* :bug:`179`: Fix a missing variable causing errors when an ssh_config file has +* :bug:`179` Fix a missing variable causing errors when an ssh_config file has a non-default AddressFamily set. Thanks to Ed Marshall & Tomaz Muraus for catch & patch. -* :bug:`200`: Fix an exception-causing typo in `demo_simple.py`. Thanks to Alex +* :bug:`200` Fix an exception-causing typo in `demo_simple.py`. Thanks to Alex Buchanan for catch & Dave Foster for patch. -* :bug:`199`: Typo fix in the license header cross-project. Thanks to Armin +* :bug:`199` Typo fix in the license header cross-project. Thanks to Armin Ronacher for catch & patch. * :release:`1.10.3 <2013-09-20>` -* :bug:`162`: Clean up HMAC module import to avoid deadlocks in certain uses of +* :bug:`162` Clean up HMAC module import to avoid deadlocks in certain uses of SSHClient. Thanks to Gernot Hillier for the catch & suggested fix. -* :bug:`36`: Fix the port-forwarding demo to avoid file descriptor errors. +* :bug:`36` Fix the port-forwarding demo to avoid file descriptor errors. Thanks to Jonathan Halcrow for catch & patch. -* :bug:`168`: Update config handling to properly handle multiple 'localforward' +* :bug:`168` Update config handling to properly handle multiple 'localforward' and 'remoteforward' keys. Thanks to Emre Yılmaz for the patch. * :release:`1.10.2 <2013-07-26>` -* :bug:`153`, :issue:`67`: Warn on parse failure when reading known_hosts +* :bug:`153` (also :issue:`67`) Warn on parse failure when reading known_hosts file. Thanks to `@glasserc` for patch. -* :bug:`146`: Indentation fixes for readability. Thanks to Abhinav Upadhyay for +* :bug:`146` Indentation fixes for readability. Thanks to Abhinav Upadhyay for catch & patch. * :release:`1.10.1 <2013-04-05>` -* :bug:`142`: (`Fabric #811 `_) +* :bug:`142` (`Fabric #811 `_) SFTP put of empty file will still return the attributes of the put file. Thanks to Jason R. Coombs for the patch. -* :bug:`154`: (`Fabric #876 `_) +* :bug:`154` (`Fabric #876 `_) Forwarded SSH agent connections left stale local pipes lying around, which could cause local (and sometimes remote or network) resource starvation when running many agent-using remote commands. Thanks to Kevin Tegtmeier for catch & patch. * :release:`1.10.0 <2013-03-01>` -* :feature:`66`: Batch SFTP writes to help speed up file transfers. Thanks to +* :feature:`66` Batch SFTP writes to help speed up file transfers. Thanks to Olle Lundberg for the patch. -* :bug:`133 major`: Fix handling of window-change events to be on-spec and not +* :bug:`133 major` Fix handling of window-change events to be on-spec and not attempt to wait for a response from the remote sshd; this fixes problems with less common targets such as some Cisco devices. Thanks to Phillip Heller for catch & patch. -* :feature:`93`: Overhaul SSH config parsing to be in line with `man +* :feature:`93` Overhaul SSH config parsing to be in line with `man ssh_config` (& the behavior of `ssh` itself), including addition of parameter expansion within config values. Thanks to Olle Lundberg for the patch. -* :feature:`110`: Honor SSH config `AddressFamily` setting when looking up +* :feature:`110` Honor SSH config `AddressFamily` setting when looking up local host's FQDN. Thanks to John Hensley for the patch. -* :feature:`128`: Defer FQDN resolution until needed, when parsing SSH config +* :feature:`128` Defer FQDN resolution until needed, when parsing SSH config files. Thanks to Parantapa Bhattacharya for catch & patch. -* :bug:`102 major`: Forego random padding for packets when running under +* :bug:`102 major` Forego random padding for packets when running under `*-ctr` ciphers. This corrects some slowdowns on platforms where random byte generation is inefficient (e.g. Windows). Thanks to `@warthog618` for catch & patch, and Michael van der Kolff for code/technique review. -* :feature:`127`: Turn `SFTPFile` into a context manager. Thanks to Michael +* :feature:`127` Turn `SFTPFile` into a context manager. Thanks to Michael Williamson for the patch. -* :feature:`116`: Limit `Message.get_bytes` to an upper bound of 1MB to protect +* :feature:`116` Limit `Message.get_bytes` to an upper bound of 1MB to protect against potential DoS vectors. Thanks to `@mvschaik` for catch & patch. -* :feature:`115`: Add convenience `get_pty` kwarg to `Client.exec_command` so +* :feature:`115` Add convenience `get_pty` kwarg to `Client.exec_command` so users not manually controlling a channel object can still toggle PTY creation. Thanks to Michael van der Kolff for the patch. -* :feature:`71`: Add `SFTPClient.putfo` and `.getfo` methods to allow direct +* :feature:`71` Add `SFTPClient.putfo` and `.getfo` methods to allow direct uploading/downloading of file-like objects. Thanks to Eric Buehl for the patch. -* :feature:`113`: Add `timeout` parameter to `SSHClient.exec_command` for +* :feature:`113` Add `timeout` parameter to `SSHClient.exec_command` for easier setting of the command's internal channel object's timeout. Thanks to Cernov Vladimir for the patch. -* :support:`94`: Remove duplication of SSH port constant. Thanks to Olle +* :support:`94` Remove duplication of SSH port constant. Thanks to Olle Lundberg for the catch. -* :feature:`80`: Expose the internal "is closed" property of the file transfer +* :feature:`80` Expose the internal "is closed" property of the file transfer class `BufferedFile` as `.closed`, better conforming to Python's file interface. Thanks to `@smunaut` and James Hiscock for catch & patch. -- cgit v1.2.3 From 87cd72c144c54fc9c6f05ff7482bd6e9e7622730 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Thu, 23 Jan 2014 11:43:34 -0800 Subject: Set up Intersphinx so www can ref docs --- sites/shared_conf.py | 2 +- sites/www/conf.py | 25 ++++++++++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/sites/shared_conf.py b/sites/shared_conf.py index 89e0a56d..c48dcdce 100644 --- a/sites/shared_conf.py +++ b/sites/shared_conf.py @@ -42,7 +42,7 @@ html_sidebars = { # Regular settings project = u'Paramiko' year = datetime.now().year -copyright = u'%d Jeff Forcier, 2003-2012 Robey Pointer' % year +copyright = u'2013-%d Jeff Forcier, 2003-2012 Robey Pointer' % year master_doc = 'index' templates_path = ['_templates'] exclude_trees = ['_build'] diff --git a/sites/www/conf.py b/sites/www/conf.py index c144b5b4..b2f96186 100644 --- a/sites/www/conf.py +++ b/sites/www/conf.py @@ -1,15 +1,30 @@ # Obtain shared config values -import os, sys -sys.path.append(os.path.abspath('..')) +import sys +import os +from os.path import abspath, join, dirname + +sys.path.append(abspath(join(dirname(__file__), '..'))) from shared_conf import * -# Add local blog extension -sys.path.append(os.path.abspath('.')) +# Local blog extension +sys.path.append(abspath('.')) extensions = ['blog'] rss_link = 'http://paramiko.org' rss_description = 'Paramiko project news' -# Add Releases changelog extension +# Releases changelog extension extensions.append('releases') releases_release_uri = "https://github.com/paramiko/paramiko/tree/%s" releases_issue_uri = "https://github.com/paramiko/paramiko/issues/%s" + +# Intersphinx for referencing API/usage docs +extensions.append('sphinx.ext.intersphinx') +# Default is 'local' building, but reference the public docs site when building +# under RTD. +target = join(dirname(__file__), '..', 'docs', '_build') +if os.environ.get('READTHEDOCS') == 'True': + # TODO: switch to docs.paramiko.org post go-live + target = 'http://paramiko-docs.readthedocs.org/en/latest/' +intersphinx_mapping = { + 'docs': (target, None), +} -- cgit v1.2.3 From 69d40710dc55373f9bbeb9f2721c6942a5250bbd Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Tue, 28 Jan 2014 08:46:21 -0800 Subject: Tweak logo settings (& rely on new alabaster defaults) --- dev-requirements.txt | 2 +- sites/shared_conf.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index a2b9a4e8..a967765c 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -3,5 +3,5 @@ invoke>=0.6.1 invocations>=0.4.4 sphinx>=1.1.3 -alabaster>=0.1.0 +alabaster>=0.2.0 releases>=0.2.4 diff --git a/sites/shared_conf.py b/sites/shared_conf.py index c48dcdce..d6852cc7 100644 --- a/sites/shared_conf.py +++ b/sites/shared_conf.py @@ -11,8 +11,6 @@ html_theme_path = [alabaster.get_path()] html_static_path = ['../_shared_static'] html_theme = 'alabaster' html_theme_options = { - 'logo': 'logo.png', - 'logo_name': 'true', 'description': "A Python implementation of SSHv2.", 'github_user': 'paramiko', 'github_repo': 'paramiko', -- cgit v1.2.3 From da51cd8b14231a3fa9850d0d1b939168ae7b0534 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Tue, 28 Jan 2014 12:50:19 -0800 Subject: Update to new alabaster-driven nav sidebar --- sites/shared_conf.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/sites/shared_conf.py b/sites/shared_conf.py index d6852cc7..267b3bc2 100644 --- a/sites/shared_conf.py +++ b/sites/shared_conf.py @@ -17,21 +17,18 @@ html_theme_options = { 'gittip_user': 'bitprophet', 'analytics_id': 'UA-18486793-2', + 'extra_nav_links': { + "API Docs": 'http://docs.paramiko.org', + }, + 'link': '#3782BE', 'link_hover': '#3782BE', } html_sidebars = { - # Landing page (no ToC) - 'index': [ - 'about.html', - 'searchbox.html', - 'donate.html', - ], - # Inner pages get a ToC '**': [ 'about.html', - 'localtoc.html', + 'navigation.html', 'searchbox.html', 'donate.html', ] -- cgit v1.2.3 From 7b690707dd81a80c7550c1f537b870805418d6df Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Tue, 28 Jan 2014 12:50:24 -0800 Subject: Don't display blog for now --- sites/www/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/sites/www/index.rst b/sites/www/index.rst index f8db6fd0..43c060b9 100644 --- a/sites/www/index.rst +++ b/sites/www/index.rst @@ -12,7 +12,6 @@ usage and API documentation can be found at our code documentation site, `docs.paramiko.org `_. .. toctree:: - blog changelog installing contributing -- cgit v1.2.3 From 414fec8f273e6807a8ee97253a5a82d0c8b787ab Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Tue, 28 Jan 2014 15:12:33 -0800 Subject: Bump Invoke requirement to newly released version w/ better Collection.from_module --- dev-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-requirements.txt b/dev-requirements.txt index a967765c..2fe1e778 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,6 +1,6 @@ # For newer tasks like building Sphinx docs. # NOTE: Requires Python >=2.6 -invoke>=0.6.1 +invoke>=0.7.0 invocations>=0.4.4 sphinx>=1.1.3 alabaster>=0.2.0 -- cgit v1.2.3 From fee04a39ec45baefff84c8a58540fa3401b4a826 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Tue, 28 Jan 2014 15:23:11 -0800 Subject: Add sites/docs building to Travis --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 29e44e53..98a54829 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,12 @@ install: # Dev (doc/test running) requirements - pip install coveralls # For coveralls.io specifically - pip install -r dev-requirements.txt -script: coverage run --source=paramiko test.py --verbose +script: + # Main tests, with coverage! + - coverage run --source=paramiko test.py --verbose + # Ensure documentation & invoke pipeline run OK + - invoke www + - invoke docs notifications: irc: channels: "irc.freenode.org#paramiko" -- cgit v1.2.3 From d1d65b4ddde17a97d25a79aeaad6c3068846cb36 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Tue, 28 Jan 2014 15:53:26 -0800 Subject: Stricter/more useful doc builds in Travis --- .travis.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 98a54829..df7c225a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,9 +11,12 @@ install: script: # Main tests, with coverage! - coverage run --source=paramiko test.py --verbose - # Ensure documentation & invoke pipeline run OK - - invoke www - - invoke docs + # Ensure documentation & invoke pipeline run OK. + # Run 'docs' first since its objects.inv is referred to by 'www'. + # Also force warnings to be errors since most of them tend to be actual + # problems. + - invoke docs -o -W + - invoke www -o -W notifications: irc: channels: "irc.freenode.org#paramiko" -- cgit v1.2.3 From b60075c7cd2fb4dd67701382f953e454d3db1848 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Tue, 28 Jan 2014 16:00:03 -0800 Subject: Prevent warning about unlinked blog page --- sites/www/index.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sites/www/index.rst b/sites/www/index.rst index 43c060b9..7fefedd2 100644 --- a/sites/www/index.rst +++ b/sites/www/index.rst @@ -17,6 +17,13 @@ usage and API documentation can be found at our code documentation site, contributing contact +.. Hide blog in hidden toctree for now (to avoid warnings.) + +.. toctree:: + :hidden: + + blog + .. rubric:: Footnotes -- cgit v1.2.3 From 2b0f834c1660c8865300e27b46a85de2edf4d556 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Wed, 29 Jan 2014 14:23:46 -0800 Subject: Move API doc sister link to www site only, derp --- sites/shared_conf.py | 5 ----- sites/www/conf.py | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sites/shared_conf.py b/sites/shared_conf.py index 267b3bc2..2b98654f 100644 --- a/sites/shared_conf.py +++ b/sites/shared_conf.py @@ -17,13 +17,8 @@ html_theme_options = { 'gittip_user': 'bitprophet', 'analytics_id': 'UA-18486793-2', - 'extra_nav_links': { - "API Docs": 'http://docs.paramiko.org', - }, - 'link': '#3782BE', 'link_hover': '#3782BE', - } html_sidebars = { '**': [ diff --git a/sites/www/conf.py b/sites/www/conf.py index b2f96186..58132d70 100644 --- a/sites/www/conf.py +++ b/sites/www/conf.py @@ -28,3 +28,8 @@ if os.environ.get('READTHEDOCS') == 'True': intersphinx_mapping = { 'docs': (target, None), } + +# Sister-site links to API docs +html_theme_options['extra_nav_links'] = { + "API Docs": 'http://docs.paramiko.org', +} -- cgit v1.2.3 From b8d1724f5714c27ad02ae013e87f5531aec041ea Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Wed, 29 Jan 2014 14:24:54 -0800 Subject: Comment out intersphinx pending #256 --- sites/www/conf.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sites/www/conf.py b/sites/www/conf.py index 58132d70..1f11c1e2 100644 --- a/sites/www/conf.py +++ b/sites/www/conf.py @@ -23,11 +23,11 @@ extensions.append('sphinx.ext.intersphinx') # under RTD. target = join(dirname(__file__), '..', 'docs', '_build') if os.environ.get('READTHEDOCS') == 'True': - # TODO: switch to docs.paramiko.org post go-live + # TODO: switch to docs.paramiko.org post go-live of sphinx API docs target = 'http://paramiko-docs.readthedocs.org/en/latest/' -intersphinx_mapping = { - 'docs': (target, None), -} +#intersphinx_mapping = { +# 'docs': (target, None), +#} # Sister-site links to API docs html_theme_options['extra_nav_links'] = { -- cgit v1.2.3 From 2b64ff4cd9921b90210b75720c452dcd4e74fe68 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Wed, 29 Jan 2014 15:05:52 -0800 Subject: Forgot to update backticks for Sphinx, derp --- sites/www/changelog.rst | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst index bba78949..71344613 100644 --- a/sites/www/changelog.rst +++ b/sites/www/changelog.rst @@ -14,7 +14,7 @@ Changelog * :bug:`179` Fix a missing variable causing errors when an ssh_config file has a non-default AddressFamily set. Thanks to Ed Marshall & Tomaz Muraus for catch & patch. -* :bug:`200` Fix an exception-causing typo in `demo_simple.py`. Thanks to Alex +* :bug:`200` Fix an exception-causing typo in ``demo_simple.py``. Thanks to Alex Buchanan for catch & Dave Foster for patch. * :bug:`199` Typo fix in the license header cross-project. Thanks to Armin Ronacher for catch & patch. @@ -27,7 +27,7 @@ Changelog and 'remoteforward' keys. Thanks to Emre Yılmaz for the patch. * :release:`1.10.2 <2013-07-26>` * :bug:`153` (also :issue:`67`) Warn on parse failure when reading known_hosts - file. Thanks to `@glasserc` for patch. + file. Thanks to ``@glasserc`` for patch. * :bug:`146` Indentation fixes for readability. Thanks to Abhinav Upadhyay for catch & patch. * :release:`1.10.1 <2013-04-05>` @@ -46,32 +46,32 @@ Changelog attempt to wait for a response from the remote sshd; this fixes problems with less common targets such as some Cisco devices. Thanks to Phillip Heller for catch & patch. -* :feature:`93` Overhaul SSH config parsing to be in line with `man - ssh_config` (& the behavior of `ssh` itself), including addition of parameter +* :feature:`93` Overhaul SSH config parsing to be in line with ``man + ssh_config`` (& the behavior of ``ssh`` itself), including addition of parameter expansion within config values. Thanks to Olle Lundberg for the patch. -* :feature:`110` Honor SSH config `AddressFamily` setting when looking up +* :feature:`110` Honor SSH config ``AddressFamily`` setting when looking up local host's FQDN. Thanks to John Hensley for the patch. * :feature:`128` Defer FQDN resolution until needed, when parsing SSH config files. Thanks to Parantapa Bhattacharya for catch & patch. * :bug:`102 major` Forego random padding for packets when running under - `*-ctr` ciphers. This corrects some slowdowns on platforms where random byte - generation is inefficient (e.g. Windows). Thanks to `@warthog618` for catch + ``*-ctr`` ciphers. This corrects some slowdowns on platforms where random byte + generation is inefficient (e.g. Windows). Thanks to ``@warthog618` for catch & patch, and Michael van der Kolff for code/technique review. -* :feature:`127` Turn `SFTPFile` into a context manager. Thanks to Michael +* :feature:`127` Turn ``SFTPFile`` into a context manager. Thanks to Michael Williamson for the patch. -* :feature:`116` Limit `Message.get_bytes` to an upper bound of 1MB to protect - against potential DoS vectors. Thanks to `@mvschaik` for catch & patch. -* :feature:`115` Add convenience `get_pty` kwarg to `Client.exec_command` so +* :feature:`116` Limit ``Message.get_bytes`` to an upper bound of 1MB to protect + against potential DoS vectors. Thanks to ``@mvschaik`` for catch & patch. +* :feature:`115` Add convenience ``get_pty`` kwarg to ``Client.exec_command`` so users not manually controlling a channel object can still toggle PTY creation. Thanks to Michael van der Kolff for the patch. -* :feature:`71` Add `SFTPClient.putfo` and `.getfo` methods to allow direct +* :feature:`71` Add ``SFTPClient.putfo`` and ``.getfo`` methods to allow direct uploading/downloading of file-like objects. Thanks to Eric Buehl for the patch. -* :feature:`113` Add `timeout` parameter to `SSHClient.exec_command` for +* :feature:`113` Add ``timeout`` parameter to ``SSHClient.exec_command`` for easier setting of the command's internal channel object's timeout. Thanks to Cernov Vladimir for the patch. * :support:`94` Remove duplication of SSH port constant. Thanks to Olle Lundberg for the catch. * :feature:`80` Expose the internal "is closed" property of the file transfer - class `BufferedFile` as `.closed`, better conforming to Python's file - interface. Thanks to `@smunaut` and James Hiscock for catch & patch. + class ``BufferedFile`` as ``.closed``, better conforming to Python's file + interface. Thanks to ``@smunaut`` and James Hiscock for catch & patch. -- cgit v1.2.3 From 6646e36673d97803cf48804eb68a73c5e5827461 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Wed, 29 Jan 2014 15:06:14 -0800 Subject: Add 1.11.0 to new changelog --- sites/www/changelog.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst index 71344613..5dfbcbbc 100644 --- a/sites/www/changelog.rst +++ b/sites/www/changelog.rst @@ -25,7 +25,22 @@ Changelog Thanks to Jonathan Halcrow for catch & patch. * :bug:`168` Update config handling to properly handle multiple 'localforward' and 'remoteforward' keys. Thanks to Emre Yılmaz for the patch. +* :release:`1.11.0 <2013-07-26>` * :release:`1.10.2 <2013-07-26>` +* :bug:`98 major` On Windows, when interacting with the PuTTY PAgeant, Paramiko + now creates the shared memory map with explicit Security Attributes of the + user, which is the same technique employed by the canonical PuTTY library to + avoid permissions issues when Paramiko is running under a different UAC + context than the PuTTY Ageant process. Thanks to Jason R. Coombs for the + patch. +* :support:`100` Remove use of PyWin32 in ``win_pageant`` module. Module was + already dependent on ctypes for constructing appropriate structures and had + ctypes implementations of all functionality. Thanks to Jason R. Coombs for + the patch. +* :bug:`87 major` Ensure updates to ``known_hosts`` files account for any + updates to said files after Paramiko initially read them. (Includes related + fix to guard against duplicate entries during subsequent ``known_hosts`` + loads.) Thanks to ``@sunweaver`` for the contribution. * :bug:`153` (also :issue:`67`) Warn on parse failure when reading known_hosts file. Thanks to ``@glasserc`` for patch. * :bug:`146` Indentation fixes for readability. Thanks to Abhinav Upadhyay for -- cgit v1.2.3 From a58ee1c89ac49bc7b250d9350bcedf59cad70fc9 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Wed, 29 Jan 2014 15:16:04 -0800 Subject: Missed a spot w/ SnR --- sites/www/changelog.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst index 5dfbcbbc..741374ce 100644 --- a/sites/www/changelog.rst +++ b/sites/www/changelog.rst @@ -69,9 +69,9 @@ Changelog * :feature:`128` Defer FQDN resolution until needed, when parsing SSH config files. Thanks to Parantapa Bhattacharya for catch & patch. * :bug:`102 major` Forego random padding for packets when running under - ``*-ctr`` ciphers. This corrects some slowdowns on platforms where random byte - generation is inefficient (e.g. Windows). Thanks to ``@warthog618` for catch - & patch, and Michael van der Kolff for code/technique review. + ``*-ctr`` ciphers. This corrects some slowdowns on platforms where random + byte generation is inefficient (e.g. Windows). Thanks to ``@warthog618`` for + catch & patch, and Michael van der Kolff for code/technique review. * :feature:`127` Turn ``SFTPFile`` into a context manager. Thanks to Michael Williamson for the patch. * :feature:`116` Limit ``Message.get_bytes`` to an upper bound of 1MB to protect -- cgit v1.2.3 From d0d711ac788ace57186d09765c173f8c6679198e Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Wed, 29 Jan 2014 15:20:49 -0800 Subject: Port 1.11.1 --- sites/www/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst index 741374ce..31359c2d 100644 --- a/sites/www/changelog.rst +++ b/sites/www/changelog.rst @@ -18,6 +18,7 @@ Changelog Buchanan for catch & Dave Foster for patch. * :bug:`199` Typo fix in the license header cross-project. Thanks to Armin Ronacher for catch & patch. +* :release:`1.11.1 <2013-09-20>` * :release:`1.10.3 <2013-09-20>` * :bug:`162` Clean up HMAC module import to avoid deadlocks in certain uses of SSHClient. Thanks to Gernot Hillier for the catch & suggested fix. -- cgit v1.2.3 From a83f0d3038e8d16e7c160293d16c2736645564d6 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Thu, 30 Jan 2014 10:40:29 -0800 Subject: Add rest of 1.11 releases --- sites/www/changelog.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst index 31359c2d..ec27dfca 100644 --- a/sites/www/changelog.rst +++ b/sites/www/changelog.rst @@ -2,15 +2,21 @@ Changelog ========= +* :release:`1.11.4 <2014-01-21>` * :release:`1.10.6 <2014-01-21>` * :bug:`193` (and its attentant PRs :issue:`230` & :issue:`253`): Fix SSH agent problems present on Windows. Thanks to David Hobbs for initial report and to Aarni Koskela & Olle Lundberg for the patches. +* :release:`1.11.3 <2014-01-08>` * :release:`1.10.5 <2014-01-08>` * :bug:`176` Fix AttributeError bugs in known_hosts file (re)loading. Thanks to Nathan Scowcroft for the patch & Martin Blumenstingl for the initial test case. -* :release:`1.10.4 <2013-09-27>` +* :release:`1.11.2 <2013-09-27>` +* :release:`1.10.4 <2013-09-27>` 179, 200, 199 +* :bug:`156` Fix potential deadlock condition when using Channel objects as + sockets (e.g. when using SSH gatewaying). Thanks to Steven Noonan and Frank + Arnold for catch & patch. * :bug:`179` Fix a missing variable causing errors when an ssh_config file has a non-default AddressFamily set. Thanks to Ed Marshall & Tomaz Muraus for catch & patch. -- cgit v1.2.3 From 14929d6909e77cbae25e1f2ac92b707a6310df22 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Thu, 30 Jan 2014 10:45:00 -0800 Subject: 1.12 releases --- sites/www/changelog.rst | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst index ec27dfca..697bc987 100644 --- a/sites/www/changelog.rst +++ b/sites/www/changelog.rst @@ -2,18 +2,35 @@ Changelog ========= +* :release:`1.12.2 <2014-01-21>` * :release:`1.11.4 <2014-01-21>` * :release:`1.10.6 <2014-01-21>` * :bug:`193` (and its attentant PRs :issue:`230` & :issue:`253`): Fix SSH agent problems present on Windows. Thanks to David Hobbs for initial report and to Aarni Koskela & Olle Lundberg for the patches. -* :release:`1.11.3 <2014-01-08>` -* :release:`1.10.5 <2014-01-08>` +* :release:`1.12.1 <2014-01-08>` +* :release:`1.11.3 <2014-01-08>` 176 +* :release:`1.10.5 <2014-01-08>` 176 +* :bug:`225` Note ecdsa requirement in README. Thanks to Amaury Rodriguez for + the catch. * :bug:`176` Fix AttributeError bugs in known_hosts file (re)loading. Thanks to Nathan Scowcroft for the patch & Martin Blumenstingl for the initial test case. +* :release:`1.12.0 <2013-09-27>` * :release:`1.11.2 <2013-09-27>` * :release:`1.10.4 <2013-09-27>` 179, 200, 199 +* :feature:`152` Add tentative support for ECDSA keys. *This adds the ecdsa + module as a new dependency of Paramiko.* The module is available at + [warner/python-ecdsa on Github](https://github.com/warner/python-ecdsa) and + [ecdsa on PyPI](https://pypi.python.org/pypi/ecdsa). + + * Note that you might still run into problems with key negotiation -- + Paramiko picks the first key that the server offers, which might not be + what you have in your known_hosts file. + * Mega thanks to Ethan Glasser-Camp for the patch. + +* #136: Add server-side support for the SSH protocol's 'env' command. Thanks to + Benjamin Pollack for the patch. * :bug:`156` Fix potential deadlock condition when using Channel objects as sockets (e.g. when using SSH gatewaying). Thanks to Steven Noonan and Frank Arnold for catch & patch. -- cgit v1.2.3 From 5ba3761f21ebdb0082ea16343c88c139063853be Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Thu, 30 Jan 2014 10:55:10 -0800 Subject: Fix some boogs in changelog --- sites/www/changelog.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst index 697bc987..9df85c4b 100644 --- a/sites/www/changelog.rst +++ b/sites/www/changelog.rst @@ -3,8 +3,8 @@ Changelog ========= * :release:`1.12.2 <2014-01-21>` -* :release:`1.11.4 <2014-01-21>` -* :release:`1.10.6 <2014-01-21>` +* :release:`1.11.4 <2014-01-21>` 193 +* :release:`1.10.6 <2014-01-21>` 193 * :bug:`193` (and its attentant PRs :issue:`230` & :issue:`253`): Fix SSH agent problems present on Windows. Thanks to David Hobbs for initial report and to Aarni Koskela & Olle Lundberg for the patches. @@ -18,7 +18,7 @@ Changelog case. * :release:`1.12.0 <2013-09-27>` * :release:`1.11.2 <2013-09-27>` -* :release:`1.10.4 <2013-09-27>` 179, 200, 199 +* :release:`1.10.4 <2013-09-27>` 199, 200, 179 * :feature:`152` Add tentative support for ECDSA keys. *This adds the ecdsa module as a new dependency of Paramiko.* The module is available at [warner/python-ecdsa on Github](https://github.com/warner/python-ecdsa) and @@ -29,8 +29,8 @@ Changelog what you have in your known_hosts file. * Mega thanks to Ethan Glasser-Camp for the patch. -* #136: Add server-side support for the SSH protocol's 'env' command. Thanks to - Benjamin Pollack for the patch. +* :feature:`136` Add server-side support for the SSH protocol's 'env' command. + Thanks to Benjamin Pollack for the patch. * :bug:`156` Fix potential deadlock condition when using Channel objects as sockets (e.g. when using SSH gatewaying). Thanks to Steven Noonan and Frank Arnold for catch & patch. -- cgit v1.2.3 From 343d0492a74e80e915f62c394c76f5b34415025b Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Thu, 30 Jan 2014 10:55:10 -0800 Subject: Backport changelog bugfix from 1.12 --- sites/www/changelog.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst index ec27dfca..6e5f6188 100644 --- a/sites/www/changelog.rst +++ b/sites/www/changelog.rst @@ -2,8 +2,8 @@ Changelog ========= -* :release:`1.11.4 <2014-01-21>` -* :release:`1.10.6 <2014-01-21>` +* :release:`1.11.4 <2014-01-21>` 193 +* :release:`1.10.6 <2014-01-21>` 193 * :bug:`193` (and its attentant PRs :issue:`230` & :issue:`253`): Fix SSH agent problems present on Windows. Thanks to David Hobbs for initial report and to Aarni Koskela & Olle Lundberg for the patches. @@ -13,7 +13,7 @@ Changelog to Nathan Scowcroft for the patch & Martin Blumenstingl for the initial test case. * :release:`1.11.2 <2013-09-27>` -* :release:`1.10.4 <2013-09-27>` 179, 200, 199 +* :release:`1.10.4 <2013-09-27>` 199, 200, 179 * :bug:`156` Fix potential deadlock condition when using Channel objects as sockets (e.g. when using SSH gatewaying). Thanks to Steven Noonan and Frank Arnold for catch & patch. -- cgit v1.2.3