payload: {"action":"created","comment":{"url":"https://api.github.com/repos/Featuretools/featuretools/pulls/comments/281774840","pull_request_review_id":234690279,"id":281774840,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDI4MTc3NDg0MA==","diff_hunk":"@@ -0,0 +1,85 @@\n+import json\n+\n+from featuretools.version import __version__ as ft_version\n+\n+SCHEMA_VERSION = \"1.0.0\"\n+\n+\n+def save_features(features, filepath):\n+    \"\"\"Saves the features list as JSON to a specificed filepath.\n+\n+    Args:\n+        features (list[:class:`.FeatureBase`]): List of Feature definitions.\n+\n+        filepath (str): The location of where to save the features list. This\n+            must include the name of the file.\n+\n+    Note:\n+        Features saved in one version of Featuretools are not guaranteed to work in another.\n+        After upgrading Featuretools, features may need to be generated again.\n+\n+    Example:\n+        .. ipython:: python\n+            :suppress:\n+\n+            from featuretools.tests.testing_utils import (\n+                make_ecommerce_entityset)\n+            import featuretools as ft\n+            es = make_ecommerce_entityset()\n+            import os\n+\n+        .. code-block:: python\n+\n+            f1 = ft.Feature(es[\"log\"][\"product_id\"])\n+            f2 = ft.Feature(es[\"log\"][\"purchased\"])\n+            f3 = ft.Feature(es[\"log\"][\"value\"])\n+\n+            features = [f1, f2, f3]\n+\n+            filepath = os.path.join('/Home/features/', 'list')\n+            ft.save_features(features, filepath)\n+    .. seealso::\n+        :func:`.load_features`\n+    \"\"\"\n+    FeaturesSerializer(features).save(filepath)\n+\n+\n+class FeaturesSerializer(object):\n+    def __init__(self, feature_list):\n+        self.feature_list = feature_list\n+\n+    def to_dict(self):\n+        names_list = [feat.unique_name() for feat in self.feature_list]\n+        es = self.feature_list[0].entityset\n+        return {\n+            'schema_version': SCHEMA_VERSION,\n+            'ft_version': ft_version,\n+            'entityset': es.to_dictionary(),\n+            'feature_list': names_list,\n+            'feature_definitions': self._feature_definitions(),\n+        }\n+\n+    def save(self, filepath):\n+        features_dict = self.to_dict()\n+        with open(filepath, \"w\") as f:\n+            json.dump(features_dict, f)\n+\n+    def _feature_definitions(self):\n+        all_features = {}","path":"featuretools/feature_base/features_serializer.py","position":68,"original_position":68,"commit_id":"b55bbd6d7a8e8bb502263761acc832166c40663b","original_commit_id":"b55bbd6d7a8e8bb502263761acc832166c40663b","user":{"login":"rwedge","id":5392142,"node_id":"MDQ6VXNlcjUzOTIxNDI=","avatar_url":"https://avatars2.githubusercontent.com/u/5392142?v=4","gravatar_id":"","url":"https://api.github.com/users/rwedge","html_url":"https://github.com/rwedge","followers_url":"https://api.github.com/users/rwedge/followers","following_url":"https://api.github.com/users/rwedge/following{/other_user}","gists_url":"https://api.github.com/users/rwedge/gists{/gist_id}","starred_url":"https://api.github.com/users/rwedge/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rwedge/subscriptions","organizations_url":"https://api.github.com/users/rwedge/orgs","repos_url":"https://api.github.com/users/rwedge/repos","events_url":"https://api.github.com/users/rwedge/events{/privacy}","received_events_url":"https://api.github.com/users/rwedge/received_events","type":"User","site_admin":false},"body":"yes.","created_at":"2019-05-07T18:33:28Z","updated_at":"2019-05-07T18:33:29Z","html_url":"https://github.com/Featuretools/featuretools/pull/532#discussion_r281774840","pull_request_url":"https://api.github.com/repos/Featuretools/featuretools/pulls/532","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/Featuretools/featuretools/pulls/comments/281774840"},"html":{"href":"https://github.com/Featuretools/featuretools/pull/532#discussion_r281774840"},"pull_request":{"href":"https://api.github.com/repos/Featuretools/featuretools/pulls/532"}},"in_reply_to_id":281707533},"pull_request":{"url":"https://api.github.com/repos/Featuretools/featuretools/pulls/532","id":276300326,"node_id":"MDExOlB1bGxSZXF1ZXN0Mjc2MzAwMzI2","html_url":"https://github.com/Featuretools/featuretools/pull/532","diff_url":"https://github.com/Featuretools/featuretools/pull/532.diff","patch_url":"https://github.com/Featuretools/featuretools/pull/532.patch","issue_url":"https://api.github.com/repos/Featuretools/featuretools/issues/532","number":532,"state":"open","locked":false,"title":"Serialize features as JSON","user":{"login":"CJStadler","id":6295246,"node_id":"MDQ6VXNlcjYyOTUyNDY=","avatar_url":"https://avatars1.githubusercontent.com/u/6295246?v=4","gravatar_id":"","url":"https://api.github.com/users/CJStadler","html_url":"https://github.com/CJStadler","followers_url":"https://api.github.com/users/CJStadler/followers","following_url":"https://api.github.com/users/CJStadler/following{/other_user}","gists_url":"https://api.github.com/users/CJStadler/gists{/gist_id}","starred_url":"https://api.github.com/users/CJStadler/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CJStadler/subscriptions","organizations_url":"https://api.github.com/users/CJStadler/orgs","repos_url":"https://api.github.com/users/CJStadler/repos","events_url":"https://api.github.com/users/CJStadler/events{/privacy}","received_events_url":"https://api.github.com/users/CJStadler/received_events","type":"User","site_admin":false},"body":"This changes the implementation of `save_features` and `load_features` to\r\nuse JSON instead of pickling. This will give us greater control over\r\nversion changes, and also makes it easier to inspect the saved data.\r\n\r\nAt the top level the JSON object has the following keys:\r\n- `schema_version`: the version of the features schema. During\r\n  deserialization if the saved version is greater than the current\r\n  version an error will be raised.\r\n- `ft_version`: the version of featuretools.\r\n- `entityset`: the entityset metadata (all features must be associated\r\n  with the same entityset).\r\n- `feature_list`: an array of the names of the features.\r\n- `feature_definitions`: an object where the keys are feature names and\r\n  the values are objects with the data for the corresponding feature.\r\n  This may include features which were not included in the given list\r\n  but are dependencies of the features in the list.\r\n\r\nEach feature object has the following keys:\r\n- `type`: the name of the class of this feature.\r\n- `dependencies`: a list of the names of features which this feature\r\n  depends on.\r\n- `arguments`: an object storing the data necessary to construct this\r\n  feature. This is generated by `feature.get_arguments` during\r\n  serialization, and passed to `feature_class.from_dictionary` during\r\n  deserialization to construct the new feature.\r\n\r\nPrimitives may be included as arguments of features, and have the\r\nfollowing keys:\r\n- `type`: the name of the primitive class.\r\n- `module`: the name of the module the primitive class is defined in.\r\n- `arguments`: an object storing the data necessary to construct this\r\n  primitive. This is built by reflecting on the signature of the\r\n  primitive's constructor and for every parameter getting the attribute\r\n  with the same name.\r\n\r\nSince primitives classes may come from different modules or be defined\r\ndynamically they are found by searching the descendants of\r\n`PrimitiveBase`.\r\n\r\nOther changes:\r\n- Move `featuretools.__version__` to its own module. This allows it to be\r\n  imported into other featuretools modules without creating a circular\r\n  dependency.\r\n- Add `EntitySet.to_dictionary()` to get the entity set metadata as a\r\n  dictionary.\r\n- Add `feature.unique_name()`, which includes the entity id. `get_name()`\r\n  may not be unique in a list of features because features on different\r\n  entities could have the same name.\r\n- Add `Timedelta.get_arguments()` and `from_dictionary`.","created_at":"2019-05-06T19:16:15Z","updated_at":"2019-05-07T18:33:29Z","closed_at":null,"merged_at":null,"merge_commit_sha":"fe6ae4b0c42d026044d7a3def56e583ce0ed6c5e","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/Featuretools/featuretools/pulls/532/commits","review_comments_url":"https://api.github.com/repos/Featuretools/featuretools/pulls/532/comments","review_comment_url":"https://api.github.com/repos/Featuretools/featuretools/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Featuretools/featuretools/issues/532/comments","statuses_url":"https://api.github.com/repos/Featuretools/featuretools/statuses/b55bbd6d7a8e8bb502263761acc832166c40663b","head":{"label":"Featuretools:features-json","ref":"features-json","sha":"b55bbd6d7a8e8bb502263761acc832166c40663b","user":{"login":"Featuretools","id":31513623,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxNTEzNjIz","avatar_url":"https://avatars1.githubusercontent.com/u/31513623?v=4","gravatar_id":"","url":"https://api.github.com/users/Featuretools","html_url":"https://github.com/Featuretools","followers_url":"https://api.github.com/users/Featuretools/followers","following_url":"https://api.github.com/users/Featuretools/following{/other_user}","gists_url":"https://api.github.com/users/Featuretools/gists{/gist_id}","starred_url":"https://api.github.com/users/Featuretools/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Featuretools/subscriptions","organizations_url":"https://api.github.com/users/Featuretools/orgs","repos_url":"https://api.github.com/users/Featuretools/repos","events_url":"https://api.github.com/users/Featuretools/events{/privacy}","received_events_url":"https://api.github.com/users/Featuretools/received_events","type":"Organization","site_admin":false},"repo":{"id":102908804,"node_id":"MDEwOlJlcG9zaXRvcnkxMDI5MDg4MDQ=","name":"featuretools","full_name":"Featuretools/featuretools","private":false,"owner":{"login":"Featuretools","id":31513623,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxNTEzNjIz","avatar_url":"https://avatars1.githubusercontent.com/u/31513623?v=4","gravatar_id":"","url":"https://api.github.com/users/Featuretools","html_url":"https://github.com/Featuretools","followers_url":"https://api.github.com/users/Featuretools/followers","following_url":"https://api.github.com/users/Featuretools/following{/other_user}","gists_url":"https://api.github.com/users/Featuretools/gists{/gist_id}","starred_url":"https://api.github.com/users/Featuretools/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Featuretools/subscriptions","organizations_url":"https://api.github.com/users/Featuretools/orgs","repos_url":"https://api.github.com/users/Featuretools/repos","events_url":"https://api.github.com/users/Featuretools/events{/privacy}","received_events_url":"https://api.github.com/users/Featuretools/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/Featuretools/featuretools","description":"An open source python framework for automated feature engineering","fork":false,"url":"https://api.github.com/repos/Featuretools/featuretools","forks_url":"https://api.github.com/repos/Featuretools/featuretools/forks","keys_url":"https://api.github.com/repos/Featuretools/featuretools/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Featuretools/featuretools/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Featuretools/featuretools/teams","hooks_url":"https://api.github.com/repos/Featuretools/featuretools/hooks","issue_events_url":"https://api.github.com/repos/Featuretools/featuretools/issues/events{/number}","events_url":"https://api.github.com/repos/Featuretools/featuretools/events","assignees_url":"https://api.github.com/repos/Featuretools/featuretools/assignees{/user}","branches_url":"https://api.github.com/repos/Featuretools/featuretools/branches{/branch}","tags_url":"https://api.github.com/repos/Featuretools/featuretools/tags","blobs_url":"https://api.github.com/repos/Featuretools/featuretools/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Featuretools/featuretools/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Featuretools/featuretools/git/refs{/sha}","trees_url":"https://api.github.com/repos/Featuretools/featuretools/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Featuretools/featuretools/statuses/{sha}","languages_url":"https://api.github.com/repos/Featuretools/featuretools/languages","stargazers_url":"https://api.github.com/repos/Featuretools/featuretools/stargazers","contributors_url":"https://api.github.com/repos/Featuretools/featuretools/contributors","subscribers_url":"https://api.github.com/repos/Featuretools/featuretools/subscribers","subscription_url":"https://api.github.com/repos/Featuretools/featuretools/subscription","commits_url":"https://api.github.com/repos/Featuretools/featuretools/commits{/sha}","git_commits_url":"https://api.github.com/repos/Featuretools/featuretools/git/commits{/sha}","comments_url":"https://api.github.com/repos/Featuretools/featuretools/comments{/number}","issue_comment_url":"https://api.github.com/repos/Featuretools/featuretools/issues/comments{/number}","contents_url":"https://api.github.com/repos/Featuretools/featuretools/contents/{+path}","compare_url":"https://api.github.com/repos/Featuretools/featuretools/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Featuretools/featuretools/merges","archive_url":"https://api.github.com/repos/Featuretools/featuretools/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Featuretools/featuretools/downloads","issues_url":"https://api.github.com/repos/Featuretools/featuretools/issues{/number}","pulls_url":"https://api.github.com/repos/Featuretools/featuretools/pulls{/number}","milestones_url":"https://api.github.com/repos/Featuretools/featuretools/milestones{/number}","notifications_url":"https://api.github.com/repos/Featuretools/featuretools/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Featuretools/featuretools/labels{/name}","releases_url":"https://api.github.com/repos/Featuretools/featuretools/releases{/id}","deployments_url":"https://api.github.com/repos/Featuretools/featuretools/deployments","created_at":"2017-09-08T22:15:17Z","updated_at":"2019-05-07T16:05:44Z","pushed_at":"2019-05-07T17:13:27Z","git_url":"git://github.com/Featuretools/featuretools.git","ssh_url":"git@github.com:Featuretools/featuretools.git","clone_url":"https://github.com/Featuretools/featuretools.git","svn_url":"https://github.com/Featuretools/featuretools","homepage":"https://www.featuretools.com","size":2863,"stargazers_count":3621,"watchers_count":3621,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":434,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":60,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause","node_id":"MDc6TGljZW5zZTU="},"forks":434,"open_issues":60,"watchers":3621,"default_branch":"master"}},"base":{"label":"Featuretools:master","ref":"master","sha":"0739b88a26f23de29971ddeae193ff3eed06c848","user":{"login":"Featuretools","id":31513623,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxNTEzNjIz","avatar_url":"https://avatars1.githubusercontent.com/u/31513623?v=4","gravatar_id":"","url":"https://api.github.com/users/Featuretools","html_url":"https://github.com/Featuretools","followers_url":"https://api.github.com/users/Featuretools/followers","following_url":"https://api.github.com/users/Featuretools/following{/other_user}","gists_url":"https://api.github.com/users/Featuretools/gists{/gist_id}","starred_url":"https://api.github.com/users/Featuretools/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Featuretools/subscriptions","organizations_url":"https://api.github.com/users/Featuretools/orgs","repos_url":"https://api.github.com/users/Featuretools/repos","events_url":"https://api.github.com/users/Featuretools/events{/privacy}","received_events_url":"https://api.github.com/users/Featuretools/received_events","type":"Organization","site_admin":false},"repo":{"id":102908804,"node_id":"MDEwOlJlcG9zaXRvcnkxMDI5MDg4MDQ=","name":"featuretools","full_name":"Featuretools/featuretools","private":false,"owner":{"login":"Featuretools","id":31513623,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxNTEzNjIz","avatar_url":"https://avatars1.githubusercontent.com/u/31513623?v=4","gravatar_id":"","url":"https://api.github.com/users/Featuretools","html_url":"https://github.com/Featuretools","followers_url":"https://api.github.com/users/Featuretools/followers","following_url":"https://api.github.com/users/Featuretools/following{/other_user}","gists_url":"https://api.github.com/users/Featuretools/gists{/gist_id}","starred_url":"https://api.github.com/users/Featuretools/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Featuretools/subscriptions","organizations_url":"https://api.github.com/users/Featuretools/orgs","repos_url":"https://api.github.com/users/Featuretools/repos","events_url":"https://api.github.com/users/Featuretools/events{/privacy}","received_events_url":"https://api.github.com/users/Featuretools/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/Featuretools/featuretools","description":"An open source python framework for automated feature engineering","fork":false,"url":"https://api.github.com/repos/Featuretools/featuretools","forks_url":"https://api.github.com/repos/Featuretools/featuretools/forks","keys_url":"https://api.github.com/repos/Featuretools/featuretools/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Featuretools/featuretools/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Featuretools/featuretools/teams","hooks_url":"https://api.github.com/repos/Featuretools/featuretools/hooks","issue_events_url":"https://api.github.com/repos/Featuretools/featuretools/issues/events{/number}","events_url":"https://api.github.com/repos/Featuretools/featuretools/events","assignees_url":"https://api.github.com/repos/Featuretools/featuretools/assignees{/user}","branches_url":"https://api.github.com/repos/Featuretools/featuretools/branches{/branch}","tags_url":"https://api.github.com/repos/Featuretools/featuretools/tags","blobs_url":"https://api.github.com/repos/Featuretools/featuretools/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Featuretools/featuretools/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Featuretools/featuretools/git/refs{/sha}","trees_url":"https://api.github.com/repos/Featuretools/featuretools/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Featuretools/featuretools/statuses/{sha}","languages_url":"https://api.github.com/repos/Featuretools/featuretools/languages","stargazers_url":"https://api.github.com/repos/Featuretools/featuretools/stargazers","contributors_url":"https://api.github.com/repos/Featuretools/featuretools/contributors","subscribers_url":"https://api.github.com/repos/Featuretools/featuretools/subscribers","subscription_url":"https://api.github.com/repos/Featuretools/featuretools/subscription","commits_url":"https://api.github.com/repos/Featuretools/featuretools/commits{/sha}","git_commits_url":"https://api.github.com/repos/Featuretools/featuretools/git/commits{/sha}","comments_url":"https://api.github.com/repos/Featuretools/featuretools/comments{/number}","issue_comment_url":"https://api.github.com/repos/Featuretools/featuretools/issues/comments{/number}","contents_url":"https://api.github.com/repos/Featuretools/featuretools/contents/{+path}","compare_url":"https://api.github.com/repos/Featuretools/featuretools/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Featuretools/featuretools/merges","archive_url":"https://api.github.com/repos/Featuretools/featuretools/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Featuretools/featuretools/downloads","issues_url":"https://api.github.com/repos/Featuretools/featuretools/issues{/number}","pulls_url":"https://api.github.com/repos/Featuretools/featuretools/pulls{/number}","milestones_url":"https://api.github.com/repos/Featuretools/featuretools/milestones{/number}","notifications_url":"https://api.github.com/repos/Featuretools/featuretools/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Featuretools/featuretools/labels{/name}","releases_url":"https://api.github.com/repos/Featuretools/featuretools/releases{/id}","deployments_url":"https://api.github.com/repos/Featuretools/featuretools/deployments","created_at":"2017-09-08T22:15:17Z","updated_at":"2019-05-07T16:05:44Z","pushed_at":"2019-05-07T17:13:27Z","git_url":"git://github.com/Featuretools/featuretools.git","ssh_url":"git@github.com:Featuretools/featuretools.git","clone_url":"https://github.com/Featuretools/featuretools.git","svn_url":"https://github.com/Featuretools/featuretools","homepage":"https://www.featuretools.com","size":2863,"stargazers_count":3621,"watchers_count":3621,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":434,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":60,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause","node_id":"MDc6TGljZW5zZTU="},"forks":434,"open_issues":60,"watchers":3621,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Featuretools/featuretools/pulls/532"},"html":{"href":"https://github.com/Featuretools/featuretools/pull/532"},"issue":{"href":"https://api.github.com/repos/Featuretools/featuretools/issues/532"},"comments":{"href":"https://api.github.com/repos/Featuretools/featuretools/issues/532/comments"},"review_comments":{"href":"https://api.github.com/repos/Featuretools/featuretools/pulls/532/comments"},"review_comment":{"href":"https://api.github.com/repos/Featuretools/featuretools/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Featuretools/featuretools/pulls/532/commits"},"statuses":{"href":"https://api.github.com/repos/Featuretools/featuretools/statuses/b55bbd6d7a8e8bb502263761acc832166c40663b"}},"author_association":"CONTRIBUTOR"}}
other: {"actor":{"display_login":"rwedge"}}