From 008fb370ec355011a048087f80fd154e886e4b6e Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Mon, 5 Aug 2013 00:36:19 -0400 Subject: Turn things into oslo.version Split oslo.version out into its own library. --- .gitreview | 2 +- CONTRIBUTING.rst | 2 +- README.rst | 170 +------------- doc/source/_templates/.placeholder | 0 doc/source/_theme/layout.html | 83 ------- doc/source/_theme/theme.conf | 4 - doc/source/conf.py | 6 +- doc/source/index.rst | 8 +- doc/source/static/basic.css | 416 ----------------------------------- doc/source/static/default.css | 230 ------------------- doc/source/static/header-line.gif | Bin 48 -> 0 bytes doc/source/static/header_bg.jpg | Bin 3738 -> 0 bytes doc/source/static/jquery.tweet.js | 154 ------------- doc/source/static/nature.css | 245 --------------------- doc/source/static/openstack_logo.png | Bin 3670 -> 0 bytes doc/source/static/tweaks.css | 94 -------- oslo/__init__.py | 15 ++ oslo/version/tests/__init__.py | 55 +++++ oslo/version/tests/test_version.py | 60 +++++ oslo/version/version.py | 274 +++++++++++++++++++++++ pbr/tests/__init__.py | 53 ----- pbr/tests/test_version.py | 60 ----- pbr/version.py | 271 ----------------------- setup.cfg | 21 +- setup.py | 6 +- test-requirements.txt | 11 + tox.ini | 6 +- 27 files changed, 435 insertions(+), 1811 deletions(-) delete mode 100644 doc/source/_templates/.placeholder delete mode 100644 doc/source/_theme/layout.html delete mode 100644 doc/source/_theme/theme.conf delete mode 100644 doc/source/static/basic.css delete mode 100644 doc/source/static/default.css delete mode 100644 doc/source/static/header-line.gif delete mode 100644 doc/source/static/header_bg.jpg delete mode 100644 doc/source/static/jquery.tweet.js delete mode 100644 doc/source/static/nature.css delete mode 100644 doc/source/static/openstack_logo.png delete mode 100644 doc/source/static/tweaks.css create mode 100644 oslo/__init__.py create mode 100644 oslo/version/tests/__init__.py create mode 100644 oslo/version/tests/test_version.py create mode 100644 oslo/version/version.py delete mode 100644 pbr/tests/__init__.py delete mode 100644 pbr/tests/test_version.py delete mode 100644 pbr/version.py create mode 100644 test-requirements.txt diff --git a/.gitreview b/.gitreview index 8df2996..0a578aa 100644 --- a/.gitreview +++ b/.gitreview @@ -1,4 +1,4 @@ [gerrit] host=review.openstack.org port=29418 -project=openstack-dev/pbr.git +project=openstack/oslo.version.git diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 3115f03..88b16aa 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -14,4 +14,4 @@ Pull requests submitted through GitHub will be ignored. Bugs should be filed on Launchpad, not GitHub: - https://bugs.launchpad.net/pbr + https://bugs.launchpad.net/oslo diff --git a/README.rst b/README.rst index 09e4135..6945de8 100644 --- a/README.rst +++ b/README.rst @@ -1,171 +1,5 @@ Introduction ============ -PBR is a library that injects some useful and sensible default behaviors -into your setuptools run. It started off life as the chunks of code that -were copied between all of the OpenStack projects. Around the time that -OpenStack hit 18 different projects each with at least 3 active branches, -it seems like a good time to make that code into a proper re-usable library. - -PBR is only mildly configurable. The basic idea is that there's a decent -way to run things and if you do, you should reap the rewards, because then -it's simple and repeatable. If you want to do things differently, cool! But -you've already got the power of python at your fingertips, so you don't -really need PBR. - -PBR builds on top of the work that `d2to1` started to provide for declarative -configuration. `d2to1` is itself an implementation of the ideas behind -`distutils2`. Although `distutils2` is now abandoned in favor of work towards -PEP 426 and Metadata 2.0, declarative config is still a great idea and -specifically important in trying to distribute setup code as a library -when that library itself will alter how the setup is processed. As Metadata -2.0 and other modern Python packaging PEPs come out, `pbr` aims to support -them as quickly as possible. - -`pbr` reads and then filters the `setup.cfg` data through a setup hook to -fill in default values and provide more sensible behaviors, and then feeds -the results in as the arguments to a call to `setup.py` - so the heavy -lifting of handling python packaging needs is still being done by -`setuptools`. - -Behaviors -========= - -What It Does ------------- - -PBR can and does do a bunch of things for you: - - * **Version**: Manage version number bad on git revisions and tags - * **AUTHORS**: Generate AUTHORS file from git log - * **ChangeLog**: Generate ChangeLog from git log - * **Sphinx Autodoc**: Generate autodoc stub files for your whole module - * **Requirements**: Store your dependencies in a pip requirements file - * **long_description**: Use your README file as a long_description - * **Smart find_packages**: Smartly find packages under your root package - -Version -^^^^^^^ - -Version strings will be inferred from git. If a given revision is tagged, -that's the version. If it's not, and you don't provide a version, the version -will be very similar to git describe. If you do, then we'll assume that's the -version you are working towards, and will generate alpha version strings -based on commits since last tag and the current git sha. - -AUTHORS and ChangeLog -^^^^^^^^^^^^^^^^^^^^^ - -Why keep an AUTHORS or a ChangeLog file, when git already has all of the -information you need. AUTHORS generation supports filtering/combining based -on a standard .mailmap file. - -Sphinx Autodoc -^^^^^^^^^^^^^^ - -Sphinx can produce auto documentation indexes based on signatures and -docstrings of your project- but you have to give it index files to tell it -to autodoc each module. That's kind of repetitive and boring. PBR will -scan your project, find all of your modules, and generate all of the stub -files for you. - -Sphinx documentation setups are altered to generate man pages by default. They -also have several pieces of information that are known to setup.py injected -into the sphinx config. - -Requirements -^^^^^^^^^^^^ - -You may not have noticed, but there are differences in how pip -requirements.txt files work and how distutils wants to be told about -requirements. The pip way is nicer, because it sure does make it easier to -popuplate a virtualenv for testing, or to just install everything you need. -Duplicating the information, though, is super lame. So PBR will let you -keep requirements.txt format files around describing the requirements for -your project, will parse them and split them up approprirately, and inject -them into the install_requires and/or tests_require and/or dependency_links -arguments to setup. Voila! - -long_description -^^^^^^^^^^^^^^^^ - -There is no need to maintain two long descriptions- and your README file is -probably a good long_description. So we'll just inject the contents of your -README.rst, README.txt or README file into your empty long_description. Yay -for you. - -Usage -===== -pbr requires a distribution to use distribute. Your distribution -must include a distutils2-like setup.cfg file, and a minimal setup.py script. - -A simple sample can be found in pbr s own setup.cfg -(it uses its own machinery to install itself):: - - [metadata] - name = pbr - author = OpenStack Foundation - author-email = openstack-dev@lists.openstack.org - summary = OpenStack's setup automation in a reuable form - description-file = README - license = Apache-2 - classifier = - Development Status :: 4 - Beta - Environment :: Console - Environment :: OpenStack - Intended Audience :: Developers - Intended Audience :: Information Technology - License :: OSI Approved :: Apache Software License - Operating System :: OS Independent - Programming Language :: Python - keywords = - setup - distutils - [files] - packages = - oslo - [hooks] - setup-hooks = - pbr.hooks.setup_hook - -The minimal setup.py should look something like this:: - - #!/usr/bin/env python - - from setuptools import setup - - setup( - setup_requires=['pbr'], - pbr=True, - ) - -Note that it's important to specify `pbr=True` or else the pbr functionality -will not be enabled. - -It should also work fine if additional arguments are passed to `setup()`, -but it should be noted that they will be clobbered by any options in the -setup.cfg file. - -Running Tests -============= -The testing system is based on a combination of tox and testr. The canonical -approach to running tests is to simply run the command `tox`. This will -create virtual environments, populate them with depenedencies and run all of -the tests that OpenStack CI systems run. Behind the scenes, tox is running -`testr run --parallel`, but is set up such that you can supply any additional -testr arguments that are needed to tox. For example, you can run: -`tox -- --analyze-isolation` to cause tox to tell testr to add ---analyze-isolation to its argument list. - -It is also possible to run the tests inside of a virtual environment -you have created, or it is possible that you have all of the dependencies -installed locally already. If you'd like to go this route, the requirements -are listed in requirements.txt and the requirements for testing are in -test-requirements.txt. Installing them via pip, for instance, is simply:: - - pip install -r requirements.txt -r test-requirements.txt - -In you go this route, you can interact with the testr command directly. -Running `testr run` will run the entire test suite. `testr run --parallel` -will run it in parallel (this is the default incantation tox uses.) More -information about testr can be found at: http://wiki.openstack.org/testr +oslo.version handles getting the version for an installed piece of software +from the python metadata that already exists. diff --git a/doc/source/_templates/.placeholder b/doc/source/_templates/.placeholder deleted file mode 100644 index e69de29..0000000 diff --git a/doc/source/_theme/layout.html b/doc/source/_theme/layout.html deleted file mode 100644 index 8a01e1a..0000000 --- a/doc/source/_theme/layout.html +++ /dev/null @@ -1,83 +0,0 @@ -{% extends "basic/layout.html" %} -{% set css_files = css_files + ['_static/tweaks.css'] %} -{% set script_files = script_files + ['_static/jquery.tweet.js'] %} - -{%- macro sidebar() %} - {%- if not embedded %}{% if not theme_nosidebar|tobool %} -
-
- {%- block sidebarlogo %} - {%- if logo %} - - {%- endif %} - {%- endblock %} - {%- block sidebartoc %} - {%- if display_toc %} -

{{ _('Table Of Contents') }}

- {{ toc }} - {%- endif %} - {%- endblock %} - {%- block sidebarrel %} - {%- if prev %} -

{{ _('Previous topic') }}

-

{{ prev.title }}

- {%- endif %} - {%- if next %} -

{{ _('Next topic') }}

-

{{ next.title }}

- {%- endif %} - {%- endblock %} - {%- block sidebarsourcelink %} - {%- if show_source and has_source and sourcename %} -

{{ _('This Page') }}

- - {%- endif %} - {%- endblock %} - {%- if customsidebar %} - {% include customsidebar %} - {%- endif %} - {%- block sidebarsearch %} - {%- if pagename != "search" %} - - - {%- endif %} - {%- endblock %} -
-
- {%- endif %}{% endif %} -{%- endmacro %} - -{% block relbar1 %}{% endblock relbar1 %} - -{% block header %} - -{% endblock %} diff --git a/doc/source/_theme/theme.conf b/doc/source/_theme/theme.conf deleted file mode 100644 index 1cc4004..0000000 --- a/doc/source/_theme/theme.conf +++ /dev/null @@ -1,4 +0,0 @@ -[theme] -inherit = basic -stylesheet = nature.css -pygments_style = tango diff --git a/doc/source/conf.py b/doc/source/conf.py index 101ef13..82fa87b 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -8,14 +8,14 @@ sys.path.insert(0, os.path.abspath('../..')) # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx'] +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'oslo.sphinx'] # autodoc generation is a bit aggressive and a nuisance when doing heavy # text edit cycles. # execute "export SPHINX_DEBUG=1" in your terminal to disable # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = [] # The suffix of source filenames. source_suffix = '.rst' @@ -24,7 +24,7 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = 'pbr' +project = 'oslo.version' copyright = '2013, OpenStack Foundation' # If true, '()' will be appended to :func: etc. cross-reference text. diff --git a/doc/source/index.rst b/doc/source/index.rst index 266988a..8bc4c00 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -1,9 +1,7 @@ -pbr - Python Build Reasonableness -================================= +oslo.version - version handling +=============================== -A library for managing setuptools packaging needs in a consistent manner. - -PBR is not a library about beer. +A library for managing versions of installed software at runtime Indices and tables ================== diff --git a/doc/source/static/basic.css b/doc/source/static/basic.css deleted file mode 100644 index d909ce3..0000000 --- a/doc/source/static/basic.css +++ /dev/null @@ -1,416 +0,0 @@ -/** - * Sphinx stylesheet -- basic theme - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -/* -- main layout ----------------------------------------------------------- */ - -div.clearer { - clear: both; -} - -/* -- relbar ---------------------------------------------------------------- */ - -div.related { - width: 100%; - font-size: 90%; -} - -div.related h3 { - display: none; -} - -div.related ul { - margin: 0; - padding: 0 0 0 10px; - list-style: none; -} - -div.related li { - display: inline; -} - -div.related li.right { - float: right; - margin-right: 5px; -} - -/* -- sidebar --------------------------------------------------------------- */ - -div.sphinxsidebarwrapper { - padding: 10px 5px 0 10px; -} - -div.sphinxsidebar { - float: left; - width: 230px; - margin-left: -100%; - font-size: 90%; -} - -div.sphinxsidebar ul { - list-style: none; -} - -div.sphinxsidebar ul ul, -div.sphinxsidebar ul.want-points { - margin-left: 20px; - list-style: square; -} - -div.sphinxsidebar ul ul { - margin-top: 0; - margin-bottom: 0; -} - -div.sphinxsidebar form { - margin-top: 10px; -} - -div.sphinxsidebar input { - border: 1px solid #98dbcc; - font-family: sans-serif; - font-size: 1em; -} - -img { - border: 0; -} - -/* -- search page ----------------------------------------------------------- */ - -ul.search { - margin: 10px 0 0 20px; - padding: 0; -} - -ul.search li { - padding: 5px 0 5px 20px; - background-image: url(file.png); - background-repeat: no-repeat; - background-position: 0 7px; -} - -ul.search li a { - font-weight: bold; -} - -ul.search li div.context { - color: #888; - margin: 2px 0 0 30px; - text-align: left; -} - -ul.keywordmatches li.goodmatch a { - font-weight: bold; -} - -/* -- index page ------------------------------------------------------------ */ - -table.contentstable { - width: 90%; -} - -table.contentstable p.biglink { - line-height: 150%; -} - -a.biglink { - font-size: 1.3em; -} - -span.linkdescr { - font-style: italic; - padding-top: 5px; - font-size: 90%; -} - -/* -- general index --------------------------------------------------------- */ - -table.indextable td { - text-align: left; - vertical-align: top; -} - -table.indextable dl, table.indextable dd { - margin-top: 0; - margin-bottom: 0; -} - -table.indextable tr.pcap { - height: 10px; -} - -table.indextable tr.cap { - margin-top: 10px; - background-color: #f2f2f2; -} - -img.toggler { - margin-right: 3px; - margin-top: 3px; - cursor: pointer; -} - -/* -- general body styles --------------------------------------------------- */ - -a.headerlink { - visibility: hidden; -} - -h1:hover > a.headerlink, -h2:hover > a.headerlink, -h3:hover > a.headerlink, -h4:hover > a.headerlink, -h5:hover > a.headerlink, -h6:hover > a.headerlink, -dt:hover > a.headerlink { - visibility: visible; -} - -div.body p.caption { - text-align: inherit; -} - -div.body td { - text-align: left; -} - -.field-list ul { - padding-left: 1em; -} - -.first { -} - -p.rubric { - margin-top: 30px; - font-weight: bold; -} - -/* -- sidebars -------------------------------------------------------------- */ - -div.sidebar { - margin: 0 0 0.5em 1em; - border: 1px solid #ddb; - padding: 7px 7px 0 7px; - background-color: #ffe; - width: 40%; - float: right; -} - -p.sidebar-title { - font-weight: bold; -} - -/* -- topics ---------------------------------------------------------------- */ - -div.topic { - border: 1px solid #ccc; - padding: 7px 7px 0 7px; - margin: 10px 0 10px 0; -} - -p.topic-title { - font-size: 1.1em; - font-weight: bold; - margin-top: 10px; -} - -/* -- admonitions ----------------------------------------------------------- */ - -div.admonition { - margin-top: 10px; - margin-bottom: 10px; - padding: 7px; -} - -div.admonition dt { - font-weight: bold; -} - -div.admonition dl { - margin-bottom: 0; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -/* -- tables ---------------------------------------------------------------- */ - -table.docutils { - border: 0; - border-collapse: collapse; -} - -table.docutils td, table.docutils th { - padding: 1px 8px 1px 0; - border-top: 0; - border-left: 0; - border-right: 0; - border-bottom: 1px solid #aaa; -} - -table.field-list td, table.field-list th { - border: 0 !important; -} - -table.footnote td, table.footnote th { - border: 0 !important; -} - -th { - text-align: left; - padding-right: 5px; -} - -/* -- other body styles ----------------------------------------------------- */ - -dl { - margin-bottom: 15px; -} - -dd p { - margin-top: 0px; -} - -dd ul, dd table { - margin-bottom: 10px; -} - -dd { - margin-top: 3px; - margin-bottom: 10px; - margin-left: 30px; -} - -dt:target, .highlight { - background-color: #fbe54e; -} - -dl.glossary dt { - font-weight: bold; - font-size: 1.1em; -} - -.field-list ul { - margin: 0; - padding-left: 1em; -} - -.field-list p { - margin: 0; -} - -.refcount { - color: #060; -} - -.optional { - font-size: 1.3em; -} - -.versionmodified { - font-style: italic; -} - -.system-message { - background-color: #fda; - padding: 5px; - border: 3px solid red; -} - -.footnote:target { - background-color: #ffa -} - -.line-block { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} - -.line-block .line-block { - margin-top: 0; - margin-bottom: 0; - margin-left: 1.5em; -} - -/* -- code displays --------------------------------------------------------- */ - -pre { - overflow: auto; -} - -td.linenos pre { - padding: 5px 0px; - border: 0; - background-color: transparent; - color: #aaa; -} - -table.highlighttable { - margin-left: 0.5em; -} - -table.highlighttable td { - padding: 0 0.5em 0 0.5em; -} - -tt.descname { - background-color: transparent; - font-weight: bold; - font-size: 1.2em; -} - -tt.descclassname { - background-color: transparent; -} - -tt.xref, a tt { - background-color: transparent; - font-weight: bold; -} - -h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { - background-color: transparent; -} - -/* -- math display ---------------------------------------------------------- */ - -img.math { - vertical-align: middle; -} - -div.body div.math p { - text-align: center; -} - -span.eqno { - float: right; -} - -/* -- printout stylesheet --------------------------------------------------- */ - -@media print { - div.document, - div.documentwrapper, - div.bodywrapper { - margin: 0 !important; - width: 100%; - } - - div.sphinxsidebar, - div.related, - div.footer, - #top-link { - display: none; - } -} diff --git a/doc/source/static/default.css b/doc/source/static/default.css deleted file mode 100644 index c8091ec..0000000 --- a/doc/source/static/default.css +++ /dev/null @@ -1,230 +0,0 @@ -/** - * Sphinx stylesheet -- default theme - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -@import url("basic.css"); - -/* -- page layout ----------------------------------------------------------- */ - -body { - font-family: sans-serif; - font-size: 100%; - background-color: #11303d; - color: #000; - margin: 0; - padding: 0; -} - -div.document { - background-color: #1c4e63; -} - -div.documentwrapper { - float: left; - width: 100%; -} - -div.bodywrapper { - margin: 0 0 0 230px; -} - -div.body { - background-color: #ffffff; - color: #000000; - padding: 0 20px 30px 20px; -} - -div.footer { - color: #ffffff; - width: 100%; - padding: 9px 0 9px 0; - text-align: center; - font-size: 75%; -} - -div.footer a { - color: #ffffff; - text-decoration: underline; -} - -div.related { - background-color: #133f52; - line-height: 30px; - color: #ffffff; -} - -div.related a { - color: #ffffff; -} - -div.sphinxsidebar { -} - -div.sphinxsidebar h3 { - font-family: 'Trebuchet MS', sans-serif; - color: #ffffff; - font-size: 1.4em; - font-weight: normal; - margin: 0; - padding: 0; -} - -div.sphinxsidebar h3 a { - color: #ffffff; -} - -div.sphinxsidebar h4 { - font-family: 'Trebuchet MS', sans-serif; - color: #ffffff; - font-size: 1.3em; - font-weight: normal; - margin: 5px 0 0 0; - padding: 0; -} - -div.sphinxsidebar p { - color: #ffffff; -} - -div.sphinxsidebar p.topless { - margin: 5px 10px 10px 10px; -} - -div.sphinxsidebar ul { - margin: 10px; - padding: 0; - color: #ffffff; -} - -div.sphinxsidebar a { - color: #98dbcc; -} - -div.sphinxsidebar input { - border: 1px solid #98dbcc; - font-family: sans-serif; - font-size: 1em; -} - -/* -- body styles ----------------------------------------------------------- */ - -a { - color: #355f7c; - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -div.body p, div.body dd, div.body li { - text-align: left; - line-height: 130%; -} - -div.body h1, -div.body h2, -div.body h3, -div.body h4, -div.body h5, -div.body h6 { - font-family: 'Trebuchet MS', sans-serif; - background-color: #f2f2f2; - font-weight: normal; - color: #20435c; - border-bottom: 1px solid #ccc; - margin: 20px -20px 10px -20px; - padding: 3px 0 3px 10px; -} - -div.body h1 { margin-top: 0; font-size: 200%; } -div.body h2 { font-size: 160%; } -div.body h3 { font-size: 140%; } -div.body h4 { font-size: 120%; } -div.body h5 { font-size: 110%; } -div.body h6 { font-size: 100%; } - -a.headerlink { - color: #c60f0f; - font-size: 0.8em; - padding: 0 4px 0 4px; - text-decoration: none; -} - -a.headerlink:hover { - background-color: #c60f0f; - color: white; -} - -div.body p, div.body dd, div.body li { - text-align: left; - line-height: 130%; -} - -div.admonition p.admonition-title + p { - display: inline; -} - -div.admonition p { - margin-bottom: 5px; -} - -div.admonition pre { - margin-bottom: 5px; -} - -div.admonition ul, div.admonition ol { - margin-bottom: 5px; -} - -div.note { - background-color: #eee; - border: 1px solid #ccc; -} - -div.seealso { - background-color: #ffc; - border: 1px solid #ff6; -} - -div.topic { - background-color: #eee; -} - -div.warning { - background-color: #ffe4e4; - border: 1px solid #f66; -} - -p.admonition-title { - display: inline; -} - -p.admonition-title:after { - content: ":"; -} - -pre { - padding: 5px; - background-color: #eeffcc; - color: #333333; - line-height: 120%; - border: 1px solid #ac9; - border-left: none; - border-right: none; -} - -tt { - background-color: #ecf0f3; - padding: 0 1px 0 1px; - font-size: 0.95em; -} - -.warning tt { - background: #efc2c2; -} - -.note tt { - background: #d6d6d6; -} diff --git a/doc/source/static/header-line.gif b/doc/source/static/header-line.gif deleted file mode 100644 index 3601730..0000000 Binary files a/doc/source/static/header-line.gif and /dev/null differ diff --git a/doc/source/static/header_bg.jpg b/doc/source/static/header_bg.jpg deleted file mode 100644 index f788c41..0000000 Binary files a/doc/source/static/header_bg.jpg and /dev/null differ diff --git a/doc/source/static/jquery.tweet.js b/doc/source/static/jquery.tweet.js deleted file mode 100644 index 7533d59..0000000 --- a/doc/source/static/jquery.tweet.js +++ /dev/null @@ -1,154 +0,0 @@ -(function($) { - - $.fn.tweet = function(o){ - var s = { - username: ["seaofclouds"], // [string] required, unless you want to display our tweets. :) it can be an array, just do ["username1","username2","etc"] - list: null, //[string] optional name of list belonging to username - avatar_size: null, // [integer] height and width of avatar if displayed (48px max) - count: 3, // [integer] how many tweets to display? - intro_text: null, // [string] do you want text BEFORE your your tweets? - outro_text: null, // [string] do you want text AFTER your tweets? - join_text: null, // [string] optional text in between date and tweet, try setting to "auto" - auto_join_text_default: "i said,", // [string] auto text for non verb: "i said" bullocks - auto_join_text_ed: "i", // [string] auto text for past tense: "i" surfed - auto_join_text_ing: "i am", // [string] auto tense for present tense: "i was" surfing - auto_join_text_reply: "i replied to", // [string] auto tense for replies: "i replied to" @someone "with" - auto_join_text_url: "i was looking at", // [string] auto tense for urls: "i was looking at" http:... - loading_text: null, // [string] optional loading text, displayed while tweets load - query: null // [string] optional search query - }; - - if(o) $.extend(s, o); - - $.fn.extend({ - linkUrl: function() { - var returning = []; - var regexp = /((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi; - this.each(function() { - returning.push(this.replace(regexp,"$1")); - }); - return $(returning); - }, - linkUser: function() { - var returning = []; - var regexp = /[\@]+([A-Za-z0-9-_]+)/gi; - this.each(function() { - returning.push(this.replace(regexp,"@$1")); - }); - return $(returning); - }, - linkHash: function() { - var returning = []; - var regexp = / [\#]+([A-Za-z0-9-_]+)/gi; - this.each(function() { - returning.push(this.replace(regexp, ' #$1')); - }); - return $(returning); - }, - capAwesome: function() { - var returning = []; - this.each(function() { - returning.push(this.replace(/\b(awesome)\b/gi, '$1')); - }); - return $(returning); - }, - capEpic: function() { - var returning = []; - this.each(function() { - returning.push(this.replace(/\b(epic)\b/gi, '$1')); - }); - return $(returning); - }, - makeHeart: function() { - var returning = []; - this.each(function() { - returning.push(this.replace(/(<)+[3]/gi, "")); - }); - return $(returning); - } - }); - - function relative_time(time_value) { - var parsed_date = Date.parse(time_value); - var relative_to = (arguments.length > 1) ? arguments[1] : new Date(); - var delta = parseInt((relative_to.getTime() - parsed_date) / 1000); - var pluralize = function (singular, n) { - return '' + n + ' ' + singular + (n == 1 ? '' : 's'); - }; - if(delta < 60) { - return 'less than a minute ago'; - } else if(delta < (45*60)) { - return 'about ' + pluralize("minute", parseInt(delta / 60)) + ' ago'; - } else if(delta < (24*60*60)) { - return 'about ' + pluralize("hour", parseInt(delta / 3600)) + ' ago'; - } else { - return 'about ' + pluralize("day", parseInt(delta / 86400)) + ' ago'; - } - } - - function build_url() { - var proto = ('https:' == document.location.protocol ? 'https:' : 'http:'); - if (s.list) { - return proto+"//api.twitter.com/1/"+s.username[0]+"/lists/"+s.list+"/statuses.json?per_page="+s.count+"&callback=?"; - } else if (s.query == null && s.username.length == 1) { - return proto+'//twitter.com/status/user_timeline/'+s.username[0]+'.json?count='+s.count+'&callback=?'; - } else { - var query = (s.query || 'from:'+s.username.join('%20OR%20from:')); - return proto+'//search.twitter.com/search.json?&q='+query+'&rpp='+s.count+'&callback=?'; - } - } - - return this.each(function(){ - var list = $('