{"action":"closed","number":113,"pull_request":{"url":"https://api.github.com/repos/ripgarpr/garpr/pulls/113","id":84574782,"html_url":"https://github.com/ripgarpr/garpr/pull/113","diff_url":"https://github.com/ripgarpr/garpr/pull/113.diff","patch_url":"https://github.com/ripgarpr/garpr/pull/113.patch","issue_url":"https://api.github.com/repos/ripgarpr/garpr/issues/113","number":113,"state":"closed","locked":false,"title":"Lightweight ORM for GarPR","user":{"login":"jschnei","id":1710171,"avatar_url":"https://avatars.githubusercontent.com/u/1710171?v=3","gravatar_id":"","url":"https://api.github.com/users/jschnei","html_url":"https://github.com/jschnei","followers_url":"https://api.github.com/users/jschnei/followers","following_url":"https://api.github.com/users/jschnei/following{/other_user}","gists_url":"https://api.github.com/users/jschnei/gists{/gist_id}","starred_url":"https://api.github.com/users/jschnei/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jschnei/subscriptions","organizations_url":"https://api.github.com/users/jschnei/orgs","repos_url":"https://api.github.com/users/jschnei/repos","events_url":"https://api.github.com/users/jschnei/events{/privacy}","received_events_url":"https://api.github.com/users/jschnei/received_events","type":"User","site_admin":false},"body":"After messing around with #110 for a while, it seems pretty annoying to control exactly what queries MongoEngine is making (in particular, it really likes making extra queries to mongo to dereference objectids). This PR is an alternative to #110 and uses a custom-built lightweight ORM instead of MongoEngine (see orm.py). \r\n\r\nThe syntax is loosely inspired by [MongoEngine](http://docs.mongoengine.org/apireference.html)/[Marshmallow](https://marshmallow.readthedocs.io/en/latest/) and is hopefully intuitive for the most part (see model.py for examples). Unlike with #110, this PR runs exactly the same queries as master; in particular, queries are still specified in raw pymongo (which I think is probably for the better). Overall I recommend using this over #110 .\r\n\r\nThe code passes all tests and should be able to be merged into master with no issues. Some miscellaneous other details:\r\n\r\n- I still need to add tests and (some sort of) documentation for orm.py. A lot of the features of orm.py are tested through test_model.py, but there should be specific unit tests for orm.py.\r\n- Migrations should be much easier; most of the time you should just be able to add or remove fields from the appropriate model and it should work as is. It would be nice to have a framework for more complicated migrations, though (e.g., something like [alembic](http://alembic.zzzcomputing.com/en/latest/); I might work on this soon).\r\n- I made all the core code (the python files in root and scraper/) PEP8 compliant. We might want to stick to this from now on, as much as is reasonable.","created_at":"2016-09-09T00:08:12Z","updated_at":"2016-09-13T08:49:00Z","closed_at":"2016-09-13T08:48:59Z","merged_at":"2016-09-13T08:48:59Z","merge_commit_sha":"8b0caf33fd317a8ad278df45d46c8add828b1fe5","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/ripgarpr/garpr/pulls/113/commits","review_comments_url":"https://api.github.com/repos/ripgarpr/garpr/pulls/113/comments","review_comment_url":"https://api.github.com/repos/ripgarpr/garpr/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ripgarpr/garpr/issues/113/comments","statuses_url":"https://api.github.com/repos/ripgarpr/garpr/statuses/d2394ab849a0c94638fbf832c51aa1c8dbd65716","head":{"label":"ripgarpr:jon-backend-orm","ref":"jon-backend-orm","sha":"d2394ab849a0c94638fbf832c51aa1c8dbd65716","user":{"login":"ripgarpr","id":19935346,"avatar_url":"https://avatars.githubusercontent.com/u/19935346?v=3","gravatar_id":"","url":"https://api.github.com/users/ripgarpr","html_url":"https://github.com/ripgarpr","followers_url":"https://api.github.com/users/ripgarpr/followers","following_url":"https://api.github.com/users/ripgarpr/following{/other_user}","gists_url":"https://api.github.com/users/ripgarpr/gists{/gist_id}","starred_url":"https://api.github.com/users/ripgarpr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ripgarpr/subscriptions","organizations_url":"https://api.github.com/users/ripgarpr/orgs","repos_url":"https://api.github.com/users/ripgarpr/repos","events_url":"https://api.github.com/users/ripgarpr/events{/privacy}","received_events_url":"https://api.github.com/users/ripgarpr/received_events","type":"Organization","site_admin":false},"repo":{"id":33511266,"name":"garpr","full_name":"ripgarpr/garpr","owner":{"login":"ripgarpr","id":19935346,"avatar_url":"https://avatars.githubusercontent.com/u/19935346?v=3","gravatar_id":"","url":"https://api.github.com/users/ripgarpr","html_url":"https://github.com/ripgarpr","followers_url":"https://api.github.com/users/ripgarpr/followers","following_url":"https://api.github.com/users/ripgarpr/following{/other_user}","gists_url":"https://api.github.com/users/ripgarpr/gists{/gist_id}","starred_url":"https://api.github.com/users/ripgarpr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ripgarpr/subscriptions","organizations_url":"https://api.github.com/users/ripgarpr/orgs","repos_url":"https://api.github.com/users/ripgarpr/repos","events_url":"https://api.github.com/users/ripgarpr/events{/privacy}","received_events_url":"https://api.github.com/users/ripgarpr/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ripgarpr/garpr","description":"the revival of GarPR. may gar rest in RIP","fork":true,"url":"https://api.github.com/repos/ripgarpr/garpr","forks_url":"https://api.github.com/repos/ripgarpr/garpr/forks","keys_url":"https://api.github.com/repos/ripgarpr/garpr/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ripgarpr/garpr/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ripgarpr/garpr/teams","hooks_url":"https://api.github.com/repos/ripgarpr/garpr/hooks","issue_events_url":"https://api.github.com/repos/ripgarpr/garpr/issues/events{/number}","events_url":"https://api.github.com/repos/ripgarpr/garpr/events","assignees_url":"https://api.github.com/repos/ripgarpr/garpr/assignees{/user}","branches_url":"https://api.github.com/repos/ripgarpr/garpr/branches{/branch}","tags_url":"https://api.github.com/repos/ripgarpr/garpr/tags","blobs_url":"https://api.github.com/repos/ripgarpr/garpr/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ripgarpr/garpr/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ripgarpr/garpr/git/refs{/sha}","trees_url":"https://api.github.com/repos/ripgarpr/garpr/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ripgarpr/garpr/statuses/{sha}","languages_url":"https://api.github.com/repos/ripgarpr/garpr/languages","stargazers_url":"https://api.github.com/repos/ripgarpr/garpr/stargazers","contributors_url":"https://api.github.com/repos/ripgarpr/garpr/contributors","subscribers_url":"https://api.github.com/repos/ripgarpr/garpr/subscribers","subscription_url":"https://api.github.com/repos/ripgarpr/garpr/subscription","commits_url":"https://api.github.com/repos/ripgarpr/garpr/commits{/sha}","git_commits_url":"https://api.github.com/repos/ripgarpr/garpr/git/commits{/sha}","comments_url":"https://api.github.com/repos/ripgarpr/garpr/comments{/number}","issue_comment_url":"https://api.github.com/repos/ripgarpr/garpr/issues/comments{/number}","contents_url":"https://api.github.com/repos/ripgarpr/garpr/contents/{+path}","compare_url":"https://api.github.com/repos/ripgarpr/garpr/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ripgarpr/garpr/merges","archive_url":"https://api.github.com/repos/ripgarpr/garpr/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ripgarpr/garpr/downloads","issues_url":"https://api.github.com/repos/ripgarpr/garpr/issues{/number}","pulls_url":"https://api.github.com/repos/ripgarpr/garpr/pulls{/number}","milestones_url":"https://api.github.com/repos/ripgarpr/garpr/milestones{/number}","notifications_url":"https://api.github.com/repos/ripgarpr/garpr/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ripgarpr/garpr/labels{/name}","releases_url":"https://api.github.com/repos/ripgarpr/garpr/releases{/id}","deployments_url":"https://api.github.com/repos/ripgarpr/garpr/deployments","created_at":"2015-04-06T23:31:23Z","updated_at":"2016-08-22T23:51:02Z","pushed_at":"2016-09-13T08:49:00Z","git_url":"git://github.com/ripgarpr/garpr.git","ssh_url":"git@github.com:ripgarpr/garpr.git","clone_url":"https://github.com/ripgarpr/garpr.git","svn_url":"https://github.com/ripgarpr/garpr","homepage":"","size":12465,"stargazers_count":5,"watchers_count":5,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":29,"forks":5,"open_issues":29,"watchers":5,"default_branch":"master"}},"base":{"label":"ripgarpr:master","ref":"master","sha":"0624c6ea2e72fee5d96c2390b2ef5382a13837a4","user":{"login":"ripgarpr","id":19935346,"avatar_url":"https://avatars.githubusercontent.com/u/19935346?v=3","gravatar_id":"","url":"https://api.github.com/users/ripgarpr","html_url":"https://github.com/ripgarpr","followers_url":"https://api.github.com/users/ripgarpr/followers","following_url":"https://api.github.com/users/ripgarpr/following{/other_user}","gists_url":"https://api.github.com/users/ripgarpr/gists{/gist_id}","starred_url":"https://api.github.com/users/ripgarpr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ripgarpr/subscriptions","organizations_url":"https://api.github.com/users/ripgarpr/orgs","repos_url":"https://api.github.com/users/ripgarpr/repos","events_url":"https://api.github.com/users/ripgarpr/events{/privacy}","received_events_url":"https://api.github.com/users/ripgarpr/received_events","type":"Organization","site_admin":false},"repo":{"id":33511266,"name":"garpr","full_name":"ripgarpr/garpr","owner":{"login":"ripgarpr","id":19935346,"avatar_url":"https://avatars.githubusercontent.com/u/19935346?v=3","gravatar_id":"","url":"https://api.github.com/users/ripgarpr","html_url":"https://github.com/ripgarpr","followers_url":"https://api.github.com/users/ripgarpr/followers","following_url":"https://api.github.com/users/ripgarpr/following{/other_user}","gists_url":"https://api.github.com/users/ripgarpr/gists{/gist_id}","starred_url":"https://api.github.com/users/ripgarpr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ripgarpr/subscriptions","organizations_url":"https://api.github.com/users/ripgarpr/orgs","repos_url":"https://api.github.com/users/ripgarpr/repos","events_url":"https://api.github.com/users/ripgarpr/events{/privacy}","received_events_url":"https://api.github.com/users/ripgarpr/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ripgarpr/garpr","description":"the revival of GarPR. may gar rest in RIP","fork":true,"url":"https://api.github.com/repos/ripgarpr/garpr","forks_url":"https://api.github.com/repos/ripgarpr/garpr/forks","keys_url":"https://api.github.com/repos/ripgarpr/garpr/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ripgarpr/garpr/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ripgarpr/garpr/teams","hooks_url":"https://api.github.com/repos/ripgarpr/garpr/hooks","issue_events_url":"https://api.github.com/repos/ripgarpr/garpr/issues/events{/number}","events_url":"https://api.github.com/repos/ripgarpr/garpr/events","assignees_url":"https://api.github.com/repos/ripgarpr/garpr/assignees{/user}","branches_url":"https://api.github.com/repos/ripgarpr/garpr/branches{/branch}","tags_url":"https://api.github.com/repos/ripgarpr/garpr/tags","blobs_url":"https://api.github.com/repos/ripgarpr/garpr/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ripgarpr/garpr/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ripgarpr/garpr/git/refs{/sha}","trees_url":"https://api.github.com/repos/ripgarpr/garpr/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ripgarpr/garpr/statuses/{sha}","languages_url":"https://api.github.com/repos/ripgarpr/garpr/languages","stargazers_url":"https://api.github.com/repos/ripgarpr/garpr/stargazers","contributors_url":"https://api.github.com/repos/ripgarpr/garpr/contributors","subscribers_url":"https://api.github.com/repos/ripgarpr/garpr/subscribers","subscription_url":"https://api.github.com/repos/ripgarpr/garpr/subscription","commits_url":"https://api.github.com/repos/ripgarpr/garpr/commits{/sha}","git_commits_url":"https://api.github.com/repos/ripgarpr/garpr/git/commits{/sha}","comments_url":"https://api.github.com/repos/ripgarpr/garpr/comments{/number}","issue_comment_url":"https://api.github.com/repos/ripgarpr/garpr/issues/comments{/number}","contents_url":"https://api.github.com/repos/ripgarpr/garpr/contents/{+path}","compare_url":"https://api.github.com/repos/ripgarpr/garpr/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ripgarpr/garpr/merges","archive_url":"https://api.github.com/repos/ripgarpr/garpr/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ripgarpr/garpr/downloads","issues_url":"https://api.github.com/repos/ripgarpr/garpr/issues{/number}","pulls_url":"https://api.github.com/repos/ripgarpr/garpr/pulls{/number}","milestones_url":"https://api.github.com/repos/ripgarpr/garpr/milestones{/number}","notifications_url":"https://api.github.com/repos/ripgarpr/garpr/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ripgarpr/garpr/labels{/name}","releases_url":"https://api.github.com/repos/ripgarpr/garpr/releases{/id}","deployments_url":"https://api.github.com/repos/ripgarpr/garpr/deployments","created_at":"2015-04-06T23:31:23Z","updated_at":"2016-08-22T23:51:02Z","pushed_at":"2016-09-13T08:49:00Z","git_url":"git://github.com/ripgarpr/garpr.git","ssh_url":"git@github.com:ripgarpr/garpr.git","clone_url":"https://github.com/ripgarpr/garpr.git","svn_url":"https://github.com/ripgarpr/garpr","homepage":"","size":12465,"stargazers_count":5,"watchers_count":5,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"open_issues_count":29,"forks":5,"open_issues":29,"watchers":5,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ripgarpr/garpr/pulls/113"},"html":{"href":"https://github.com/ripgarpr/garpr/pull/113"},"issue":{"href":"https://api.github.com/repos/ripgarpr/garpr/issues/113"},"comments":{"href":"https://api.github.com/repos/ripgarpr/garpr/issues/113/comments"},"review_comments":{"href":"https://api.github.com/repos/ripgarpr/garpr/pulls/113/comments"},"review_comment":{"href":"https://api.github.com/repos/ripgarpr/garpr/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ripgarpr/garpr/pulls/113/commits"},"statuses":{"href":"https://api.github.com/repos/ripgarpr/garpr/statuses/d2394ab849a0c94638fbf832c51aa1c8dbd65716"}},"merged":true,"mergeable":null,"mergeable_state":"unknown","merged_by":{"login":"jschnei","id":1710171,"avatar_url":"https://avatars.githubusercontent.com/u/1710171?v=3","gravatar_id":"","url":"https://api.github.com/users/jschnei","html_url":"https://github.com/jschnei","followers_url":"https://api.github.com/users/jschnei/followers","following_url":"https://api.github.com/users/jschnei/following{/other_user}","gists_url":"https://api.github.com/users/jschnei/gists{/gist_id}","starred_url":"https://api.github.com/users/jschnei/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jschnei/subscriptions","organizations_url":"https://api.github.com/users/jschnei/orgs","repos_url":"https://api.github.com/users/jschnei/repos","events_url":"https://api.github.com/users/jschnei/events{/privacy}","received_events_url":"https://api.github.com/users/jschnei/received_events","type":"User","site_admin":false},"comments":0,"review_comments":0,"commits":5,"additions":2079,"deletions":2062,"changed_files":25}}
{"actor":{"display_login":"jschnei"}}