{"action":"created","comment":{"url":"https://api.github.com/repos/Kitware/tangelo/pulls/comments/23608705","id":23608705,"diff_hunk":"@@ -0,0 +1,360 @@\n+===============================================\n+    Driving a Visualization with SQLAlchemy\n+===============================================\n+\n+This tutorial demonstrates how you might set up a SQL database to serve data to\n+a visualization application using Tangelo.  This example demonstrates how an\n+application-specific approach to building and using a database can provide\n+flexibility and adaptability for your Tangelo application.\n+\n+In this tutorial we will\n+\n+- obtain *Star Trek: The Next Generation* episode data\n+- create an SQLite database from it\n+- establish some object-relational mapping (ORM) classes using SQLAlchemy\n+- visualize the data using `Vega <http://trifacta.github.io/vega>`_\n+\n+To begin this tutorial, create a fresh directory somewhere where we can build\n+a new project: ::\n+\n+    mkdir tng\n+    cd tng\n+\n+Here, we will create a database, along with appropriate ORM infrastructure;\n+write some web services to be used as runtime data sources to pull requested\n+data from the database; and a simple web frontend made from HTML and JavaScript,\n+using the Vega visualization library.\n+\n+For convenience, you can download and unpack a ZIP archive of the entire web\n+application as well: `tng.zip <../_static/tng.zip>`_.  However, downloading and\n+inspecting the files as we go, or writing them by hand from the listings below,\n+may encourage a deeper understanding of what's going on.\n+\n+Getting the Data\n+================\n+\n+The episode data, gleaned from `Memory Alpha <http://memory-alpha.org>`_ by\n+hand, is in these two CSV files:\n+\n+- `episodes.csv <../_static/tng/episodes.csv>`_\n+- `people.csv <../_static/tng/people.csv>`_\n+\n+If you take a look in these files, you'll see some basic data about episodes of\n+*Star Trek: The Next Generation*.  *episodes.csv* contains one row per episode,\n+indicating its overall episode number, season/episode, title, airdate, a link to\n+the associated Memory Alpha article, and numeric indices into *people.csv* to\n+indicate who wrote each teleplay, who developed each story, and who directed\n+each episode.\n+\n+Creating the Database\n+=====================\n+\n+SQLAlchemy is a Python library that provides a programmatic API for creating,\n+updating, and accessing SQLite databases.  It includes an *object-relational\n+mapping (ORM)* component, meaning it provides facilities for writing Python\n+classes that transparently maintain a connection to the database, changing it as\n+the object is updated, etc.\n+\n+Establishing ORM Classes\n+------------------------\n+\n+The first step in this visualization project is to establish our data model by\n+writing some ORM classes, then using those classes to read in the CSV files from\n+above and flow them into an SQLite database.  The file `startrek.py\n+<../_static/tng/startrek.py>`_ has what we need.  Let's analyze it, section by\n+section.\n+\n+First, we need some support from ``SQLAlchemy``:\n+\n+.. literalinclude:: ../static/tng/startrek.py\n+    :lines: 1-8\n+    :linenos:\n+\n+``create_engine`` simply gives us a handle to a database - this one will exist\n+on disk, in the file ``tngeps.db``.  The ``echo`` keyword argument controls\n+whether the behind-the-scenes translation to SQL commands will appear on the\n+output when changes occur.  For now it may be a good idea to leave this set to\n+``True`` for the sake of education.\n+\n+``declarative_base`` is a base class that provides the foundation for creating\n+ORM classes to model our data, while the ``sessionmaker`` function creates a\n+function that can be used to establish a connection to the database.\n+\n+Next we need to import some types for the columns appearing in our data:\n+\n+.. literalinclude:: ../static/tng/startrek.py\n+    :lines: 11-14\n+    :lineno-start: 11\n+    :linenos:\n+\n+``Date`` and ``String`` will be used to store actual data values, such as\n+airdates, and names of people and episodes.  ``Integer`` is useful as a unique\n+ID field for the various objects we will be storing.\n+\n+Now, we finally get to the data modeling:\n+\n+.. literalinclude:: ../static/tng/startrek.py\n+    :lines: 17-59\n+    :lineno-start: 17\n+    :linenos:\n+\n+First take a look at the classes ``Episode`` and ``Person``.  These make use of\n+SQLAlchemy's ``declarative_base`` to establish classes whose structure reflect\n+the semantics of a table in the database.  The ``__tablename__`` attribute gives\n+the name of the associated table, while the other named attributes give the\n+names of the columns appearing in it, along with the data type.\n+\n+Note that the ``teleplay``, ``story``, and ``director`` attributes of\n+``Episode`` are a bit more complex than the others.  These are fields that\n+cross-reference into the \"people\" table:  each ``Episode`` may have\n+multiple writers and story developers [#f1]_, each of which is a ``Person``.  Of\n+course, a particular Person may also be associated with multiple Episodes, so a\n+special \"many-to-many\" relationship exists between ``Episode`` and ``Person``\n+when it comes to the ``teleplay``, ``story``, and ``director`` columns.  These\n+are expressed in the \"association table\" declarations appearing in lines 25, 29,\n+and 33.  Such tables simply contain one row for each unique episode-person\n+connection; they are referenced in the appropriate column declaration (lines\n+46-48) to implement the many-to-many relation.\n+\n+The effect of these ORM classes is that when, e.g., an ``Episode`` object is\n+queried from the database, its ``teleplay`` property will contain a list of the\n+correct ``Person`` objects, having been reconstructed by examining the\n+\"episode_teleplays\" table in the database.\n+\n+Creating the Database\n+---------------------\n+\n+Now it just remains to use the ORM infrastructure to drive the parsing of the\n+raw data and creation of the actual database.  The file `build-db.py\n+<../_static/tng/build-db.py>`_ contains a Python script to do just this.  Let's\n+examine this script, section by section.  First, as always, we need to import\n+some standard modules:\n+\n+.. literalinclude:: ../static/tng/build-db.py\n+    :lines: 1-3\n+    :linenos:\n+\n+Next, we need some stuff from *startrek.py*:\n+\n+.. literalinclude:: ../static/tng/build-db.py\n+    :lines: 5-9\n+    :linenos:\n+    :lineno-start: 5\n+\n+Now, let's go ahead and slurp in the raw data from the CSV files:\n+\n+.. literalinclude:: ../static/tng/build-db.py\n+    :lines: 12-19\n+    :linenos:\n+    :lineno-start: 12\n+\n+We now have two lists, ``episodes`` and ``people``, containing the row data.\n+Before we continue, we need to \"activate\" the ORM classes, and connect to the\n+database:\n+\n+.. literalinclude:: ../static/tng/build-db.py\n+    :lines: 22-23\n+    :linenos:\n+    :lineno-start: 22\n+\n+Now let's add the rows from *people.csv* to the database:\n+\n+.. literalinclude:: ../static/tng/build-db.py\n+    :lines: 26-33\n+    :linenos:\n+    :lineno-start: 26\n+\n+This loop simply runs through the rows of the people data (excluding the first\n+\"row,\" which is just the header descriptors), saving each in a table indexed by\n+ID:  line 30 creates a ``Person`` object, while line 33 causes a row in the\n+appropriate tables to be created in the database (using ORM magic).  We want the\n+saved table so we can reference ``Person`` objects later.\n+\n+Now that we have all the people loaded up, we can put the episode data itself\n+into the database:\n+\n+.. literalinclude:: ../static/tng/build-db.py\n+    :lines: 37-58\n+    :linenos:\n+    :lineno-start: 37\n+\n+This is a loop running through the rows of the episode data, pulling out the\n+various fields, possibly converting them to appropriate Python types.  The\n+``teleplay``, ``story``, and ``director`` columns in particular are converted to\n+lists of ``Person`` objects (by looking up the appropriate ``Person`` in the\n+table we created earlier).  Line 58 adds the newly created ``Person`` to the\n+database.  The many-to-many relationships we established earlier will be invoked\n+here, updating the association tables according to the ``Person`` objects\n+present in each ``Episode`` object's fields.\n+\n+Finally, we must commit the accumulated database operations:\n+\n+.. literalinclude:: ../static/tng/build-db.py\n+    :lines: 61-\n+    :linenos:\n+    :lineno-start: 61\n+\n+If you have downloaded the data files, *startrek.py*, and *build-db.py* all to\n+the same directory, you should be able to build the database with this command::\n+\n+    python build-db.py\n+\n+Because we directed the database engine to echo its activity to the output, you\n+should see SQL commands fly by as they are generated by the various calls to\n+``session.add()``.  This should result in a new file being created, *tngeps.db*.\n+This is an SQLite database file, and should contain all of the data and\n+relationships established in the raw data files.\n+\n+Writing Data Services\n+=====================\n+\n+Now we have a database and some ORM classes to query it.  The next step is to\n+write a web service that can pull out some data that we need.  We are going to\n+use `Vega <http://trifacta.github.io/vega>`_ to create some basic charts of the\n+episode data, and Vega visualizations rely on data presented as a list of JSON\n+objects, one per data point.  As a starting point for a visualization project on\n+Star Trek episode data, let's tally up the number of episodes written or\n+developed by each person in the *people* table, and use Vega to render a bar\n+chart.  To do so, we need to query the database and count how many episodes each\n+person is associated to.  We can use the ORM classes to accomplish this.  Let's\n+analyze the file `writers.py <../_static/tng/writers.py>`_ to see how.  First,\n+module imports:\n+\n+.. literalinclude:: ../static/tng/writers.py\n+    :lines: 1-4\n+    :linenos:\n+\n+Now, the meat of the service, the ``run()`` function:\n+\n+.. literalinclude:: ../static/tng/writers.py\n+    :lines: 8-9\n+    :lineno-start: 8\n+    :linenos:\n+\n+The function signature says that the sort parameter, if present, should be a\n+query argument in JSON-form, defaulting to ``False``.  We will use this\n+parameter to sort the list of episode writers by the number of episodes worked\n+on (since this may be an interesting thing to look into).  Next we need a\n+connection to the database:\n+\n+.. literalinclude:: ../static/tng/writers.py\n+    :lines: 10\n+    :lineno-start: 10\n+    :linenos:\n+\n+and some logic to aggregate writers' episode counts ():\n+\n+.. literalinclude:: ../static/tng/writers.py\n+    :lines: 12-22\n+    :lineno-start: 12\n+    :linenos:\n+\n+This retrieves a list of ``Episode`` objects from the database (line 13), then\n+loops through them, incrementing a count of writers in a dictionary (being\n+careful not to double count writers listed under both *teleplay* and *story* for\n+a given episode).\n+\n+Now we convert the dictionary of collected counts into a list of objects\n+suitable for a Vega visualization:\n+\n+.. literalinclude:: ../static/tng/writers.py\n+    :lines: 24-\n+    :lineno-start: 24\n+    :linenos:\n+\n+This line converts each ``Person`` object into a Python dictionary after sorting\n+by the numeric ID (which, because of how the data was collected, roughly\n+corresponds to the order of first involvement in writing for *Star Trek: The\n+Next Generation*).  If the ``sort`` parameter was ``True``, then the results\n+will be sorted by descending episode count (so that the most frequent writers\n+will appear first, etc.).  And finally, of course, the function returns this\n+list of results.\n+\n+With this file written we have the start of a web application.  To see how\n+things stand, you can launch Tangelo to serve this directory to the web,\n+\n+.. code-block:: shell\n+\n+    tangelo --root .\n+\n+and then visit http://localhost:8080/writers to see the list of JSON objects\n+that results.","path":"docs/tutorials/db-vis.rst","position":281,"original_position":281,"commit_id":"d88f52eb55ec72b7b627d215b8cb4cac2d45c875","original_commit_id":"d88f52eb55ec72b7b627d215b8cb4cac2d45c875","user":{"login":"jeffbaumes","id":81305,"avatar_url":"https://avatars.githubusercontent.com/u/81305?v=3","gravatar_id":"","url":"https://api.github.com/users/jeffbaumes","html_url":"https://github.com/jeffbaumes","followers_url":"https://api.github.com/users/jeffbaumes/followers","following_url":"https://api.github.com/users/jeffbaumes/following{/other_user}","gists_url":"https://api.github.com/users/jeffbaumes/gists{/gist_id}","starred_url":"https://api.github.com/users/jeffbaumes/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jeffbaumes/subscriptions","organizations_url":"https://api.github.com/users/jeffbaumes/orgs","repos_url":"https://api.github.com/users/jeffbaumes/repos","events_url":"https://api.github.com/users/jeffbaumes/events{/privacy}","received_events_url":"https://api.github.com/users/jeffbaumes/received_events","type":"User","site_admin":false},"body":"This does not seem to work without the `?sort=true` (or `false`). Without it I get the error:\r\n```\r\n{\"error\": \"'sort' was registered for type conversion but did not appear in the arguments list\"}\r\n```","created_at":"2015-01-27T13:56:33Z","updated_at":"2015-01-27T13:56:33Z","html_url":"https://github.com/Kitware/tangelo/pull/477#discussion_r23608705","pull_request_url":"https://api.github.com/repos/Kitware/tangelo/pulls/477","_links":{"self":{"href":"https://api.github.com/repos/Kitware/tangelo/pulls/comments/23608705"},"html":{"href":"https://github.com/Kitware/tangelo/pull/477#discussion_r23608705"},"pull_request":{"href":"https://api.github.com/repos/Kitware/tangelo/pulls/477"}}},"pull_request":{"url":"https://api.github.com/repos/Kitware/tangelo/pulls/477","id":27964227,"html_url":"https://github.com/Kitware/tangelo/pull/477","diff_url":"https://github.com/Kitware/tangelo/pull/477.diff","patch_url":"https://github.com/Kitware/tangelo/pull/477.patch","issue_url":"https://api.github.com/repos/Kitware/tangelo/issues/477","number":477,"state":"open","locked":false,"title":"Star Trek episode writers tutorial","user":{"login":"ronichoudhury","id":2903332,"avatar_url":"https://avatars.githubusercontent.com/u/2903332?v=3","gravatar_id":"","url":"https://api.github.com/users/ronichoudhury","html_url":"https://github.com/ronichoudhury","followers_url":"https://api.github.com/users/ronichoudhury/followers","following_url":"https://api.github.com/users/ronichoudhury/following{/other_user}","gists_url":"https://api.github.com/users/ronichoudhury/gists{/gist_id}","starred_url":"https://api.github.com/users/ronichoudhury/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ronichoudhury/subscriptions","organizations_url":"https://api.github.com/users/ronichoudhury/orgs","repos_url":"https://api.github.com/users/ronichoudhury/repos","events_url":"https://api.github.com/users/ronichoudhury/events{/privacy}","received_events_url":"https://api.github.com/users/ronichoudhury/received_events","type":"User","site_admin":false},"body":"I realized we already have a \"developer cookbook\" in the docs, in the Tutorials section.  This PR adds an example using CSV data to create a SQLite database with SQLAlchemy, then builds a web service and a frontend to visualize some of the data.\r\n\r\n@jeffbaumes please take a look.  I think some parts of this may not make sense as written, or as ordered.  Let me know what you think.\r\n\r\nFYI: This PR also bumps up the required Sphinx version (for development only).","created_at":"2015-01-23T23:26:56Z","updated_at":"2015-01-27T13:56:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"9c3e561b8176105cc776232e1135cba459f7a3a7","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Kitware/tangelo/pulls/477/commits","review_comments_url":"https://api.github.com/repos/Kitware/tangelo/pulls/477/comments","review_comment_url":"https://api.github.com/repos/Kitware/tangelo/pulls/comments/{number}","comments_url":"https://api.github.com/repos/Kitware/tangelo/issues/477/comments","statuses_url":"https://api.github.com/repos/Kitware/tangelo/statuses/d88f52eb55ec72b7b627d215b8cb4cac2d45c875","head":{"label":"Kitware:cookbook","ref":"cookbook","sha":"d88f52eb55ec72b7b627d215b8cb4cac2d45c875","user":{"login":"Kitware","id":87549,"avatar_url":"https://avatars.githubusercontent.com/u/87549?v=3","gravatar_id":"","url":"https://api.github.com/users/Kitware","html_url":"https://github.com/Kitware","followers_url":"https://api.github.com/users/Kitware/followers","following_url":"https://api.github.com/users/Kitware/following{/other_user}","gists_url":"https://api.github.com/users/Kitware/gists{/gist_id}","starred_url":"https://api.github.com/users/Kitware/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kitware/subscriptions","organizations_url":"https://api.github.com/users/Kitware/orgs","repos_url":"https://api.github.com/users/Kitware/repos","events_url":"https://api.github.com/users/Kitware/events{/privacy}","received_events_url":"https://api.github.com/users/Kitware/received_events","type":"Organization","site_admin":false},"repo":{"id":6885877,"name":"tangelo","full_name":"Kitware/tangelo","owner":{"login":"Kitware","id":87549,"avatar_url":"https://avatars.githubusercontent.com/u/87549?v=3","gravatar_id":"","url":"https://api.github.com/users/Kitware","html_url":"https://github.com/Kitware","followers_url":"https://api.github.com/users/Kitware/followers","following_url":"https://api.github.com/users/Kitware/following{/other_user}","gists_url":"https://api.github.com/users/Kitware/gists{/gist_id}","starred_url":"https://api.github.com/users/Kitware/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kitware/subscriptions","organizations_url":"https://api.github.com/users/Kitware/orgs","repos_url":"https://api.github.com/users/Kitware/repos","events_url":"https://api.github.com/users/Kitware/events{/privacy}","received_events_url":"https://api.github.com/users/Kitware/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Kitware/tangelo","description":"A simple, quick, powerful web framework","fork":false,"url":"https://api.github.com/repos/Kitware/tangelo","forks_url":"https://api.github.com/repos/Kitware/tangelo/forks","keys_url":"https://api.github.com/repos/Kitware/tangelo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Kitware/tangelo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Kitware/tangelo/teams","hooks_url":"https://api.github.com/repos/Kitware/tangelo/hooks","issue_events_url":"https://api.github.com/repos/Kitware/tangelo/issues/events{/number}","events_url":"https://api.github.com/repos/Kitware/tangelo/events","assignees_url":"https://api.github.com/repos/Kitware/tangelo/assignees{/user}","branches_url":"https://api.github.com/repos/Kitware/tangelo/branches{/branch}","tags_url":"https://api.github.com/repos/Kitware/tangelo/tags","blobs_url":"https://api.github.com/repos/Kitware/tangelo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Kitware/tangelo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Kitware/tangelo/git/refs{/sha}","trees_url":"https://api.github.com/repos/Kitware/tangelo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Kitware/tangelo/statuses/{sha}","languages_url":"https://api.github.com/repos/Kitware/tangelo/languages","stargazers_url":"https://api.github.com/repos/Kitware/tangelo/stargazers","contributors_url":"https://api.github.com/repos/Kitware/tangelo/contributors","subscribers_url":"https://api.github.com/repos/Kitware/tangelo/subscribers","subscription_url":"https://api.github.com/repos/Kitware/tangelo/subscription","commits_url":"https://api.github.com/repos/Kitware/tangelo/commits{/sha}","git_commits_url":"https://api.github.com/repos/Kitware/tangelo/git/commits{/sha}","comments_url":"https://api.github.com/repos/Kitware/tangelo/comments{/number}","issue_comment_url":"https://api.github.com/repos/Kitware/tangelo/issues/comments/{number}","contents_url":"https://api.github.com/repos/Kitware/tangelo/contents/{+path}","compare_url":"https://api.github.com/repos/Kitware/tangelo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Kitware/tangelo/merges","archive_url":"https://api.github.com/repos/Kitware/tangelo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Kitware/tangelo/downloads","issues_url":"https://api.github.com/repos/Kitware/tangelo/issues{/number}","pulls_url":"https://api.github.com/repos/Kitware/tangelo/pulls{/number}","milestones_url":"https://api.github.com/repos/Kitware/tangelo/milestones{/number}","notifications_url":"https://api.github.com/repos/Kitware/tangelo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Kitware/tangelo/labels{/name}","releases_url":"https://api.github.com/repos/Kitware/tangelo/releases{/id}","created_at":"2012-11-27T15:38:26Z","updated_at":"2015-01-22T15:39:06Z","pushed_at":"2015-01-23T23:22:30Z","git_url":"git://github.com/Kitware/tangelo.git","ssh_url":"git@github.com:Kitware/tangelo.git","clone_url":"https://github.com/Kitware/tangelo.git","svn_url":"https://github.com/Kitware/tangelo","homepage":"http:/tangelohub.org/tangelo/","size":10945,"stargazers_count":180,"watchers_count":180,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":30,"mirror_url":null,"open_issues_count":39,"forks":30,"open_issues":39,"watchers":180,"default_branch":"develop"}},"base":{"label":"Kitware:develop","ref":"develop","sha":"657f392f8c04e776297b55661dcb708ed10fa8a7","user":{"login":"Kitware","id":87549,"avatar_url":"https://avatars.githubusercontent.com/u/87549?v=3","gravatar_id":"","url":"https://api.github.com/users/Kitware","html_url":"https://github.com/Kitware","followers_url":"https://api.github.com/users/Kitware/followers","following_url":"https://api.github.com/users/Kitware/following{/other_user}","gists_url":"https://api.github.com/users/Kitware/gists{/gist_id}","starred_url":"https://api.github.com/users/Kitware/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kitware/subscriptions","organizations_url":"https://api.github.com/users/Kitware/orgs","repos_url":"https://api.github.com/users/Kitware/repos","events_url":"https://api.github.com/users/Kitware/events{/privacy}","received_events_url":"https://api.github.com/users/Kitware/received_events","type":"Organization","site_admin":false},"repo":{"id":6885877,"name":"tangelo","full_name":"Kitware/tangelo","owner":{"login":"Kitware","id":87549,"avatar_url":"https://avatars.githubusercontent.com/u/87549?v=3","gravatar_id":"","url":"https://api.github.com/users/Kitware","html_url":"https://github.com/Kitware","followers_url":"https://api.github.com/users/Kitware/followers","following_url":"https://api.github.com/users/Kitware/following{/other_user}","gists_url":"https://api.github.com/users/Kitware/gists{/gist_id}","starred_url":"https://api.github.com/users/Kitware/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Kitware/subscriptions","organizations_url":"https://api.github.com/users/Kitware/orgs","repos_url":"https://api.github.com/users/Kitware/repos","events_url":"https://api.github.com/users/Kitware/events{/privacy}","received_events_url":"https://api.github.com/users/Kitware/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Kitware/tangelo","description":"A simple, quick, powerful web framework","fork":false,"url":"https://api.github.com/repos/Kitware/tangelo","forks_url":"https://api.github.com/repos/Kitware/tangelo/forks","keys_url":"https://api.github.com/repos/Kitware/tangelo/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Kitware/tangelo/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Kitware/tangelo/teams","hooks_url":"https://api.github.com/repos/Kitware/tangelo/hooks","issue_events_url":"https://api.github.com/repos/Kitware/tangelo/issues/events{/number}","events_url":"https://api.github.com/repos/Kitware/tangelo/events","assignees_url":"https://api.github.com/repos/Kitware/tangelo/assignees{/user}","branches_url":"https://api.github.com/repos/Kitware/tangelo/branches{/branch}","tags_url":"https://api.github.com/repos/Kitware/tangelo/tags","blobs_url":"https://api.github.com/repos/Kitware/tangelo/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Kitware/tangelo/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Kitware/tangelo/git/refs{/sha}","trees_url":"https://api.github.com/repos/Kitware/tangelo/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Kitware/tangelo/statuses/{sha}","languages_url":"https://api.github.com/repos/Kitware/tangelo/languages","stargazers_url":"https://api.github.com/repos/Kitware/tangelo/stargazers","contributors_url":"https://api.github.com/repos/Kitware/tangelo/contributors","subscribers_url":"https://api.github.com/repos/Kitware/tangelo/subscribers","subscription_url":"https://api.github.com/repos/Kitware/tangelo/subscription","commits_url":"https://api.github.com/repos/Kitware/tangelo/commits{/sha}","git_commits_url":"https://api.github.com/repos/Kitware/tangelo/git/commits{/sha}","comments_url":"https://api.github.com/repos/Kitware/tangelo/comments{/number}","issue_comment_url":"https://api.github.com/repos/Kitware/tangelo/issues/comments/{number}","contents_url":"https://api.github.com/repos/Kitware/tangelo/contents/{+path}","compare_url":"https://api.github.com/repos/Kitware/tangelo/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Kitware/tangelo/merges","archive_url":"https://api.github.com/repos/Kitware/tangelo/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Kitware/tangelo/downloads","issues_url":"https://api.github.com/repos/Kitware/tangelo/issues{/number}","pulls_url":"https://api.github.com/repos/Kitware/tangelo/pulls{/number}","milestones_url":"https://api.github.com/repos/Kitware/tangelo/milestones{/number}","notifications_url":"https://api.github.com/repos/Kitware/tangelo/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Kitware/tangelo/labels{/name}","releases_url":"https://api.github.com/repos/Kitware/tangelo/releases{/id}","created_at":"2012-11-27T15:38:26Z","updated_at":"2015-01-22T15:39:06Z","pushed_at":"2015-01-23T23:22:30Z","git_url":"git://github.com/Kitware/tangelo.git","ssh_url":"git@github.com:Kitware/tangelo.git","clone_url":"https://github.com/Kitware/tangelo.git","svn_url":"https://github.com/Kitware/tangelo","homepage":"http:/tangelohub.org/tangelo/","size":10945,"stargazers_count":180,"watchers_count":180,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":30,"mirror_url":null,"open_issues_count":39,"forks":30,"open_issues":39,"watchers":180,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/Kitware/tangelo/pulls/477"},"html":{"href":"https://github.com/Kitware/tangelo/pull/477"},"issue":{"href":"https://api.github.com/repos/Kitware/tangelo/issues/477"},"comments":{"href":"https://api.github.com/repos/Kitware/tangelo/issues/477/comments"},"review_comments":{"href":"https://api.github.com/repos/Kitware/tangelo/pulls/477/comments"},"review_comment":{"href":"https://api.github.com/repos/Kitware/tangelo/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/Kitware/tangelo/pulls/477/commits"},"statuses":{"href":"https://api.github.com/repos/Kitware/tangelo/statuses/d88f52eb55ec72b7b627d215b8cb4cac2d45c875"}}}}