{"action":"created","comment":{"url":"https://api.github.com/repos/learning-unlimited/ESP-Website/pulls/comments/43716396","id":43716396,"diff_hunk":"@@ -1,494 +0,0 @@\n-from django.db import models\n-from django.test import TestCase\n-\n-import unittest\n-\n-from esp.cache import registry, queued\n-from esp.cache.function import cache_function\n-from esp.cache.key_set import wildcard\n-\n-# hack the cache loader so we can define more caches\n-registry._caches_locked = False\n-\n-# some test functions and models\n-\n-counter = [0]\n-@cache_function\n-def get_calls(x):\n-    counter[0] += 1\n-    return counter[0]\n-\n-class HashTag(models.Model):\n-    label = models.CharField(max_length=40, unique=True)\n-\n-    def __unicode__(self):\n-        return self.label\n-\n-class Article(models.Model):\n-    headline = models.CharField(max_length=200)\n-    content = models.TextField()\n-    reporter = models.ForeignKey('Reporter', related_name='articles')\n-    hashtags = models.ManyToManyField('HashTag', related_name='articles')\n-\n-    @cache_function\n-    def num_comments(self):\n-        return self.comments.count()\n-    num_comments.depend_on_row('cache.Comment', lambda comment: {'self': comment.article})\n-\n-    @cache_function\n-    def num_comments_with_dummy(self, dummy):\n-        return self.comments.count()\n-    num_comments_with_dummy.depend_on_row('cache.Comment', lambda comment: {'self': comment.article})\n-\n-    def __unicode__(self):\n-        return self.headline\n-\n-class Comment(models.Model):\n-    article = models.ForeignKey('Article', related_name='comments')\n-\n-class Reporter(models.Model):\n-    first_name = models.CharField(max_length=70)\n-    last_name = models.CharField(max_length=70)\n-\n-    @cache_function\n-    def full_name(self):\n-        return self.first_name + ' ' + self.last_name\n-    full_name.depend_on_row('cache.Reporter', lambda reporter: {'self': reporter})\n-\n-    @cache_function\n-    def top_article(self):\n-        articles = self.articles.all()\n-        if articles:\n-            return max(articles, key=Article.num_comments)\n-        else:\n-            return None\n-    top_article.depend_on_row(Article, lambda article: {'self': article.reporter})\n-    top_article.depend_on_cache(Article.num_comments, lambda self=wildcard: {'self': self.reporter})\n-\n-    @cache_function\n-    def articles_with_hashtag(self, hashtag='#hashtag'):\n-        return list(self.articles.filter(hashtags__label=hashtag).values_list('headline', flat=True))\n-    articles_with_hashtag.depend_on_model(HashTag)\n-    articles_with_hashtag.depend_on_row(Article, lambda article: {'self': article.reporter})\n-    articles_with_hashtag.depend_on_m2m(Article, 'hashtags', lambda article, hashtag: {'self': article.reporter, 'hashtag': hashtag.label})\n-\n-    @cache_function\n-    def articles_with_headline(self, headline):\n-        return list(self.articles.filter(headline=headline).values_list('content', flat=True))\n-    articles_with_headline.depend_on_row(Article, lambda article: {'self': article.reporter, 'headline': article.headline})\n-\n-    @cache_function\n-    def articles_with_headline_and_dummy(self, dummy, headline):\n-        return list(self.articles.filter(headline=headline).values_list('content', flat=True))\n-    articles_with_headline_and_dummy.depend_on_row(Article, lambda article: {'self': article.reporter, 'headline': article.headline})\n-\n-    def __unicode__(self):\n-        return self.full_name()\n-\n-# unhack the cache loader\n-registry._finalize_caches()\n-registry._lock_caches()\n-\n-\n-class CacheTests(TestCase):\n-    def setUp(self):\n-        # create initial objects\n-        reporter1 = Reporter.objects.create(pk=1, first_name='John', last_name='Doe')\n-        reporter2 = Reporter.objects.create(pk=2, first_name='Jane', last_name='Roe')\n-        reporter3 = Reporter.objects.create(pk=3, first_name='Jim', last_name='Poe')\n-        article1 = Article.objects.create(pk=1, headline='Breaking News', content='Lorem ipsum dolor sit amet', reporter=reporter1)\n-        article2 = Article.objects.create(pk=2, headline='Article II', content='The executive Power shall be vested in a President', reporter=reporter1)\n-        article3 = Article.objects.create(pk=3, headline='Article II', content='He shall hold his Office during the Term', reporter=reporter3)\n-        comment1 = Comment.objects.create(pk=1, article=article1)\n-        comment2 = Comment.objects.create(pk=2, article=article1)\n-        hashtag1 = HashTag.objects.create(pk=1, label='#hashtag')\n-        hashtag2 = HashTag.objects.create(pk=2, label='#news')\n-        article1.hashtags.add(hashtag2)\n-        article2.hashtags.add(hashtag1)\n-\n-    def test_caches_loaded(self):\n-        \"\"\"\n-        Rudimentary test that the loading mechanism works as expected.\n-        \"\"\"\n-        # pending lookups should be empty once everything is loaded\n-        self.assertEqual(queued.pending_lookups, {})\n-\n-        # we should test that signals are connected properly, but this\n-        # is hard to do directly. hope that if there is a problem with\n-        # that part, it ought to trip the other tests anyway.\n-\n-    def test_cached(self):\n-        \"\"\"\n-        Basic functionality: cached functions are called only on a\n-        cache miss, and retrieve the expected result on a cache hit.\n-        \"\"\"\n-        # check that we make the expected number of function calls,\n-        # and get the expected results for arguments of various types\n-        self.assertEqual(get_calls(1), 1)\n-        self.assertEqual(get_calls(()), 2)\n-        self.assertEqual(get_calls('a'), 3)\n-        self.assertEqual(get_calls(None), 4)\n-        self.assertEqual(get_calls(False), 5)\n-        self.assertEqual(get_calls(frozenset([2.0, 3.0])), 6)\n-        self.assertEqual(get_calls(frozenset([2.0, 3.0])), 6)\n-        self.assertEqual(get_calls(None), 4)\n-        self.assertEqual(get_calls(False), 5)\n-        self.assertEqual(get_calls(1), 1)\n-        self.assertEqual(get_calls(()), 2)\n-        self.assertEqual(get_calls('a'), 3)\n-        self.assertEqual(get_calls('b'), 7)\n-\n-        # check that we get the same result from calling a cached method twice\n-        # (presumably from the cache the second time)\n-        reporter = Reporter.objects.get(pk=1)\n-        name1 = reporter.full_name()\n-        name2 = reporter.full_name()\n-        self.assertEqual(name1, name2)\n-\n-        # use assertNumQueries to check that we aren't making DB queries\n-        # cache hits should not make queries\n-        article = Article.objects.get(pk=1)\n-        cnt1 = article.num_comments()\n-        with self.assertNumQueries(0):\n-            cnt2 = article.num_comments()\n-        self.assertEqual(cnt1, cnt2)\n-\n-        article_ = Article.objects.get(pk=1)\n-        with self.assertNumQueries(0):\n-            cnt3 = article_.num_comments()\n-        self.assertEqual(cnt1, cnt3)\n-\n-        top_article = reporter.top_article()\n-        self.assertEqual(top_article, max(reporter.articles.all(), key=Article.num_comments))\n-        with self.assertNumQueries(0):\n-            top_article_again = reporter.top_article()\n-        self.assertEqual(top_article, top_article_again)\n-\n-        with_hashtag = reporter.articles_with_hashtag('#hashtag')\n-        with self.assertNumQueries(0):\n-            with_hashtag_again = reporter.articles_with_hashtag('#hashtag')\n-        self.assertEqual(with_hashtag, with_hashtag_again)\n-\n-    def test_cache_none(self):\n-        \"\"\"\n-        None values can be stored in the cache.\n-        \"\"\"\n-        reporter = Reporter.objects.get(pk=2)\n-        top_article = reporter.top_article()\n-        self.assertIsNone(top_article)\n-        with self.assertNumQueries(0):\n-            top_article_again = reporter.top_article()\n-        self.assertIsNone(top_article_again)\n-\n-    def test_kwargs(self):\n-        \"\"\"\n-        Cached functions handle keyword arguments, *args, and **kwargs\n-        as expected.\n-        \"\"\"\n-        reporter = Reporter.objects.get(pk=1)\n-        # with positional arg\n-        with_hashtag1 = reporter.articles_with_hashtag('#hashtag')\n-        with self.assertNumQueries(0):\n-            # with keyword arg\n-            with_hashtag1_again = reporter.articles_with_hashtag(hashtag='#hashtag')\n-        self.assertEqual(with_hashtag1, with_hashtag1_again)\n-\n-        # with keyword arg\n-        with_hashtag2 = reporter.articles_with_hashtag(hashtag='#news')\n-        with self.assertNumQueries(0):\n-            # with *args and **kwargs\n-            args = ['#news']\n-            kwargs = {'hashtag': '#news'}\n-            with_hashtag2_args = reporter.articles_with_hashtag(*args)\n-            with_hashtag2_kwargs = reporter.articles_with_hashtag(**kwargs)\n-        self.assertEqual(with_hashtag2, with_hashtag2_args)\n-        self.assertEqual(with_hashtag2, with_hashtag2_kwargs)\n-\n-    def test_optional_args(self):\n-        \"\"\"\n-        Cached functions handle optional arguments as expected.\n-        \"\"\"\n-        reporter = Reporter.objects.get(pk=1)\n-        # with positional arg\n-        with_hashtag1 = reporter.articles_with_hashtag('#hashtag')\n-        with self.assertNumQueries(0):\n-            # omitting optional arg (defaulting to '#hashtag')\n-            with_hashtag1_again = reporter.articles_with_hashtag()\n-        self.assertEqual(with_hashtag1, with_hashtag1_again)\n-\n-    def test_depend_on_row(self):\n-        \"\"\"\n-        depend_on_row triggers cache invalidation when models are updated.\n-        \"\"\"\n-        # call the function, update the model, call the function again\n-        # should result in a cache miss\n-        article = Article.objects.get(pk=1)\n-        cnt1 = article.num_comments()\n-        article.comments.create(pk=3)\n-        with self.assertNumQueries(1):\n-            cnt2 = article.num_comments()\n-        self.assertEqual(cnt2, cnt1 + 1)\n-\n-        # unrelated DB updates should not affect the cache\n-        article2 = Article.objects.get(pk=2)\n-        article2.comments.create(pk=4)\n-        with self.assertNumQueries(0):\n-            cnt3 = article.num_comments()\n-        self.assertEqual(cnt3, cnt2)\n-\n-    @unittest.skip(\"Known issue, see Github #866\")\n-    def test_depend_on_row_with_dummy(self):\n-        \"\"\"\n-        depend_on_row still works correctly when there are other arguments to the function.\n-        \"\"\"\n-        # call the function, update the model, call the function again\n-        # should result in a cache miss\n-        article = Article.objects.get(pk=1)\n-        cnt1 = article.num_comments()\n-        article.comments.create(pk=3)\n-        with self.assertNumQueries(1):\n-            cnt2 = article.num_comments_with_dummy(None)\n-        self.assertEqual(cnt2, cnt1 + 1)\n-\n-        # unrelated DB updates should not affect the cache\n-        article2 = Article.objects.get(pk=2)\n-        article2.comments.create(pk=4)\n-        with self.assertNumQueries(0):\n-            cnt3 = article.num_comments_with_dummy(None)\n-        self.assertEqual(cnt3, cnt2)\n-\n-    def test_depend_on_row_multiple_arguments(self):\n-        '''Tests that depend_on_row works properly with multiple arguments (in this case, where all are used).'''\n-        reporter1 = Reporter.objects.get(pk=1)\n-        reporter3 = Reporter.objects.get(pk=3)\n-        # The first time around, each one should hit the cache.\n-        with self.assertNumQueries(1):\n-            arts1a = reporter1.articles_with_headline('Breaking News')\n-        with self.assertNumQueries(1):\n-            arts2a = reporter1.articles_with_headline('Article II')\n-        with self.assertNumQueries(1):\n-            arts3a = reporter3.articles_with_headline('Article II')\n-        \n-        # There were no updates, so we shouldn't hit the cache.\n-        with self.assertNumQueries(0):\n-            arts1b = reporter1.articles_with_headline('Breaking News')\n-            self.assertEqual(arts1a,arts1b)\n-        with self.assertNumQueries(0):\n-            arts2b = reporter1.articles_with_headline('Article II')\n-            self.assertEqual(arts2a,arts2b)\n-        with self.assertNumQueries(0):\n-            arts3b = reporter3.articles_with_headline('Article II')\n-            self.assertEqual(arts3a,arts3b)\n-\n-        article1 = Article.objects.get(pk=1)\n-        article1.content = 'The news is broken.'\n-        article1.save()\n-\n-        # The first query should be affected by the update, but the latter two shouldn't.\n-        with self.assertNumQueries(1):\n-            arts1c = reporter1.articles_with_headline('Breaking News')\n-            self.assertNotEqual(arts1b,arts1c)\n-        with self.assertNumQueries(0):\n-            arts2c = reporter1.articles_with_headline('Article II')\n-            self.assertEqual(arts2b,arts2c)\n-        with self.assertNumQueries(0):\n-            arts3c = reporter3.articles_with_headline('Article II')\n-            self.assertEqual(arts3b,arts3c)\n-\n-        article2 = Article.objects.get(pk=2)\n-        article2.content = 'The executive Power shall be vested in a Prime Minister'\n-        article2.save()\n-\n-        # Now only the second should be affected.\n-        with self.assertNumQueries(0):\n-            arts1d = reporter1.articles_with_headline('Breaking News')\n-            self.assertEqual(arts1c,arts1d)\n-        with self.assertNumQueries(1):\n-            arts2d = reporter1.articles_with_headline('Article II')\n-            self.assertNotEqual(arts2c,arts2d)\n-        with self.assertNumQueries(0):\n-            arts3d = reporter3.articles_with_headline('Article II')\n-            self.assertEqual(arts3c,arts3d)\n-\n-        article3 = Article.objects.get(pk=3)\n-        article3.content = 'He shall hold his Office forever'\n-        article3.save()\n-\n-        # Now only the third should be affected.\n-        with self.assertNumQueries(0):\n-            arts1e = reporter1.articles_with_headline('Breaking News')\n-            self.assertEqual(arts1d,arts1e)\n-        with self.assertNumQueries(0):\n-            arts2e = reporter1.articles_with_headline('Article II')\n-            self.assertEqual(arts2d,arts2e)\n-        with self.assertNumQueries(1):\n-            arts3e = reporter3.articles_with_headline('Article II')\n-            self.assertNotEqual(arts3d,arts3e)\n-\n-    @unittest.skip(\"Known issue, see Github #866\")","path":"esp/esp/cache/tests.py","position":328,"original_position":328,"commit_id":"7e31301cf80fd5f2ed2b204ce3bddc2a32f69ee5","original_commit_id":"7e31301cf80fd5f2ed2b204ce3bddc2a32f69ee5","user":{"login":"benjaminjkraft","id":111238,"avatar_url":"https://avatars.githubusercontent.com/u/111238?v=3","gravatar_id":"","url":"https://api.github.com/users/benjaminjkraft","html_url":"https://github.com/benjaminjkraft","followers_url":"https://api.github.com/users/benjaminjkraft/followers","following_url":"https://api.github.com/users/benjaminjkraft/following{/other_user}","gists_url":"https://api.github.com/users/benjaminjkraft/gists{/gist_id}","starred_url":"https://api.github.com/users/benjaminjkraft/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/benjaminjkraft/subscriptions","organizations_url":"https://api.github.com/users/benjaminjkraft/orgs","repos_url":"https://api.github.com/users/benjaminjkraft/repos","events_url":"https://api.github.com/users/benjaminjkraft/events{/privacy}","received_events_url":"https://api.github.com/users/benjaminjkraft/received_events","type":"User","site_admin":false},"body":"You may want to update this comment in the new one.","created_at":"2015-11-03T05:02:57Z","updated_at":"2015-11-03T05:02:57Z","html_url":"https://github.com/learning-unlimited/ESP-Website/pull/1850#discussion_r43716396","pull_request_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/pulls/1850","_links":{"self":{"href":"https://api.github.com/repos/learning-unlimited/ESP-Website/pulls/comments/43716396"},"html":{"href":"https://github.com/learning-unlimited/ESP-Website/pull/1850#discussion_r43716396"},"pull_request":{"href":"https://api.github.com/repos/learning-unlimited/ESP-Website/pulls/1850"}}},"pull_request":{"url":"https://api.github.com/repos/learning-unlimited/ESP-Website/pulls/1850","id":49510702,"html_url":"https://github.com/learning-unlimited/ESP-Website/pull/1850","diff_url":"https://github.com/learning-unlimited/ESP-Website/pull/1850.diff","patch_url":"https://github.com/learning-unlimited/ESP-Website/pull/1850.patch","issue_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/issues/1850","number":1850,"state":"open","locked":false,"title":"Move ArgCache out of the repository","user":{"login":"luac","id":1305639,"avatar_url":"https://avatars.githubusercontent.com/u/1305639?v=3","gravatar_id":"","url":"https://api.github.com/users/luac","html_url":"https://github.com/luac","followers_url":"https://api.github.com/users/luac/followers","following_url":"https://api.github.com/users/luac/following{/other_user}","gists_url":"https://api.github.com/users/luac/gists{/gist_id}","starred_url":"https://api.github.com/users/luac/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/luac/subscriptions","organizations_url":"https://api.github.com/users/luac/orgs","repos_url":"https://api.github.com/users/luac/repos","events_url":"https://api.github.com/users/luac/events{/privacy}","received_events_url":"https://api.github.com/users/luac/received_events","type":"User","site_admin":false},"body":"I spent some time over the weekend factoring ArgCache out into a separate repository. It now lives here: https://github.com/luac/django-argcache\r\n\r\nThis pull request removes the implementation of ArgCache from this repository and changes everything to depend on the new repository instead.\r\n\r\nThere's a small question of whether/how we want to continue maintaining ArgCache, as an organization. The ESP website is currently its only user, and probably will be for the foreseeable future, so any drive for changes is probably going to come from here. It might also be more convenient to have a learning-unlimited fork of it in case people would otherwise have to wait for me to accept pull requests, especially if I become less involved in ESP website development later. Other than that, I would be happy to maintain it for now. Anyone else have strong opinions on this?","created_at":"2015-11-03T01:36:52Z","updated_at":"2015-11-03T05:02:57Z","closed_at":null,"merged_at":null,"merge_commit_sha":"34233b11c8bd72e57d50f181cdab293916314803","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/pulls/1850/commits","review_comments_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/pulls/1850/comments","review_comment_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/pulls/comments{/number}","comments_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/issues/1850/comments","statuses_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/statuses/7e31301cf80fd5f2ed2b204ce3bddc2a32f69ee5","head":{"label":"learning-unlimited:argcache-external","ref":"argcache-external","sha":"7e31301cf80fd5f2ed2b204ce3bddc2a32f69ee5","user":{"login":"learning-unlimited","id":1150905,"avatar_url":"https://avatars.githubusercontent.com/u/1150905?v=3","gravatar_id":"","url":"https://api.github.com/users/learning-unlimited","html_url":"https://github.com/learning-unlimited","followers_url":"https://api.github.com/users/learning-unlimited/followers","following_url":"https://api.github.com/users/learning-unlimited/following{/other_user}","gists_url":"https://api.github.com/users/learning-unlimited/gists{/gist_id}","starred_url":"https://api.github.com/users/learning-unlimited/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/learning-unlimited/subscriptions","organizations_url":"https://api.github.com/users/learning-unlimited/orgs","repos_url":"https://api.github.com/users/learning-unlimited/repos","events_url":"https://api.github.com/users/learning-unlimited/events{/privacy}","received_events_url":"https://api.github.com/users/learning-unlimited/received_events","type":"Organization","site_admin":false},"repo":{"id":2643878,"name":"ESP-Website","full_name":"learning-unlimited/ESP-Website","owner":{"login":"learning-unlimited","id":1150905,"avatar_url":"https://avatars.githubusercontent.com/u/1150905?v=3","gravatar_id":"","url":"https://api.github.com/users/learning-unlimited","html_url":"https://github.com/learning-unlimited","followers_url":"https://api.github.com/users/learning-unlimited/followers","following_url":"https://api.github.com/users/learning-unlimited/following{/other_user}","gists_url":"https://api.github.com/users/learning-unlimited/gists{/gist_id}","starred_url":"https://api.github.com/users/learning-unlimited/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/learning-unlimited/subscriptions","organizations_url":"https://api.github.com/users/learning-unlimited/orgs","repos_url":"https://api.github.com/users/learning-unlimited/repos","events_url":"https://api.github.com/users/learning-unlimited/events{/privacy}","received_events_url":"https://api.github.com/users/learning-unlimited/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/learning-unlimited/ESP-Website","description":"A website to help manage the logistics of large short-term educational programs","fork":false,"url":"https://api.github.com/repos/learning-unlimited/ESP-Website","forks_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/forks","keys_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/keys{/key_id}","collaborators_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/teams","hooks_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/hooks","issue_events_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/issues/events{/number}","events_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/events","assignees_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/assignees{/user}","branches_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/branches{/branch}","tags_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/tags","blobs_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/git/refs{/sha}","trees_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/git/trees{/sha}","statuses_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/statuses/{sha}","languages_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/languages","stargazers_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/stargazers","contributors_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/contributors","subscribers_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/subscribers","subscription_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/subscription","commits_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/commits{/sha}","git_commits_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/git/commits{/sha}","comments_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/comments{/number}","issue_comment_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/issues/comments{/number}","contents_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/contents/{+path}","compare_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/compare/{base}...{head}","merges_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/merges","archive_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/downloads","issues_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/issues{/number}","pulls_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/pulls{/number}","milestones_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/milestones{/number}","notifications_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/labels{/name}","releases_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/releases{/id}","created_at":"2011-10-25T14:30:31Z","updated_at":"2015-10-23T23:32:59Z","pushed_at":"2015-11-03T01:36:53Z","git_url":"git://github.com/learning-unlimited/ESP-Website.git","ssh_url":"git@github.com:learning-unlimited/ESP-Website.git","clone_url":"https://github.com/learning-unlimited/ESP-Website.git","svn_url":"https://github.com/learning-unlimited/ESP-Website","homepage":"","size":60132,"stargazers_count":52,"watchers_count":52,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":38,"mirror_url":null,"open_issues_count":676,"forks":38,"open_issues":676,"watchers":52,"default_branch":"main"}},"base":{"label":"learning-unlimited:main","ref":"main","sha":"4858eb70f70dbce4bb1bbca6095092790b15fd05","user":{"login":"learning-unlimited","id":1150905,"avatar_url":"https://avatars.githubusercontent.com/u/1150905?v=3","gravatar_id":"","url":"https://api.github.com/users/learning-unlimited","html_url":"https://github.com/learning-unlimited","followers_url":"https://api.github.com/users/learning-unlimited/followers","following_url":"https://api.github.com/users/learning-unlimited/following{/other_user}","gists_url":"https://api.github.com/users/learning-unlimited/gists{/gist_id}","starred_url":"https://api.github.com/users/learning-unlimited/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/learning-unlimited/subscriptions","organizations_url":"https://api.github.com/users/learning-unlimited/orgs","repos_url":"https://api.github.com/users/learning-unlimited/repos","events_url":"https://api.github.com/users/learning-unlimited/events{/privacy}","received_events_url":"https://api.github.com/users/learning-unlimited/received_events","type":"Organization","site_admin":false},"repo":{"id":2643878,"name":"ESP-Website","full_name":"learning-unlimited/ESP-Website","owner":{"login":"learning-unlimited","id":1150905,"avatar_url":"https://avatars.githubusercontent.com/u/1150905?v=3","gravatar_id":"","url":"https://api.github.com/users/learning-unlimited","html_url":"https://github.com/learning-unlimited","followers_url":"https://api.github.com/users/learning-unlimited/followers","following_url":"https://api.github.com/users/learning-unlimited/following{/other_user}","gists_url":"https://api.github.com/users/learning-unlimited/gists{/gist_id}","starred_url":"https://api.github.com/users/learning-unlimited/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/learning-unlimited/subscriptions","organizations_url":"https://api.github.com/users/learning-unlimited/orgs","repos_url":"https://api.github.com/users/learning-unlimited/repos","events_url":"https://api.github.com/users/learning-unlimited/events{/privacy}","received_events_url":"https://api.github.com/users/learning-unlimited/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/learning-unlimited/ESP-Website","description":"A website to help manage the logistics of large short-term educational programs","fork":false,"url":"https://api.github.com/repos/learning-unlimited/ESP-Website","forks_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/forks","keys_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/keys{/key_id}","collaborators_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/teams","hooks_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/hooks","issue_events_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/issues/events{/number}","events_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/events","assignees_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/assignees{/user}","branches_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/branches{/branch}","tags_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/tags","blobs_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/git/refs{/sha}","trees_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/git/trees{/sha}","statuses_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/statuses/{sha}","languages_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/languages","stargazers_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/stargazers","contributors_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/contributors","subscribers_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/subscribers","subscription_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/subscription","commits_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/commits{/sha}","git_commits_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/git/commits{/sha}","comments_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/comments{/number}","issue_comment_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/issues/comments{/number}","contents_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/contents/{+path}","compare_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/compare/{base}...{head}","merges_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/merges","archive_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/downloads","issues_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/issues{/number}","pulls_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/pulls{/number}","milestones_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/milestones{/number}","notifications_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/labels{/name}","releases_url":"https://api.github.com/repos/learning-unlimited/ESP-Website/releases{/id}","created_at":"2011-10-25T14:30:31Z","updated_at":"2015-10-23T23:32:59Z","pushed_at":"2015-11-03T01:36:53Z","git_url":"git://github.com/learning-unlimited/ESP-Website.git","ssh_url":"git@github.com:learning-unlimited/ESP-Website.git","clone_url":"https://github.com/learning-unlimited/ESP-Website.git","svn_url":"https://github.com/learning-unlimited/ESP-Website","homepage":"","size":60132,"stargazers_count":52,"watchers_count":52,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":38,"mirror_url":null,"open_issues_count":676,"forks":38,"open_issues":676,"watchers":52,"default_branch":"main"}},"_links":{"self":{"href":"https://api.github.com/repos/learning-unlimited/ESP-Website/pulls/1850"},"html":{"href":"https://github.com/learning-unlimited/ESP-Website/pull/1850"},"issue":{"href":"https://api.github.com/repos/learning-unlimited/ESP-Website/issues/1850"},"comments":{"href":"https://api.github.com/repos/learning-unlimited/ESP-Website/issues/1850/comments"},"review_comments":{"href":"https://api.github.com/repos/learning-unlimited/ESP-Website/pulls/1850/comments"},"review_comment":{"href":"https://api.github.com/repos/learning-unlimited/ESP-Website/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/learning-unlimited/ESP-Website/pulls/1850/commits"},"statuses":{"href":"https://api.github.com/repos/learning-unlimited/ESP-Website/statuses/7e31301cf80fd5f2ed2b204ce3bddc2a32f69ee5"}}}}