1
- from contentful .cda import client
2
- from contentful .cda import resources
1
+ import contentful
3
2
from grow .common import utils
4
3
from protorpc import messages
4
+ import datetime
5
5
import grow
6
+ import json
6
7
import os
7
8
8
9
9
- class KeyMessage (messages .Message ):
10
- preview = messages .StringField (1 )
11
- production = messages .StringField (2 )
12
-
13
-
14
10
class BindingMessage (messages .Message ):
15
11
collection = messages .StringField (1 )
16
- contentModel = messages .StringField (2 )
12
+ content_type = messages .StringField (2 )
17
13
18
14
19
15
class ContentfulPreprocessor (grow .Preprocessor ):
@@ -22,22 +18,27 @@ class ContentfulPreprocessor(grow.Preprocessor):
22
18
_edit_space_url_format = 'https://app.contentful.com/spaces/{space}/entries'
23
19
_preview_endpoint = 'preview.contentful.com'
24
20
21
+ def encoder (self ):
22
+ preprocessor = self
23
+ class ContentfulEncoder (json .JSONEncoder ):
24
+ def default (self , obj ):
25
+ if isinstance (obj , datetime .datetime ):
26
+ return obj .isoformat ()
27
+ if hasattr (obj , 'type' ) and obj .type == 'Entry' :
28
+ return obj .fields ()
29
+ if hasattr (obj , 'type' ) and obj .type == 'Link' :
30
+ return obj .raw
31
+ if hasattr (obj , 'type' ) and obj .type == 'Asset' :
32
+ return obj .url ()
33
+ return json .JSONEncoder .default (self , obj )
34
+ return ContentfulEncoder
35
+
25
36
class Config (messages .Message ):
26
37
space = messages .StringField (2 )
27
- keys = messages .MessageField ( KeyMessage , 3 )
38
+ access_token = messages .StringField ( 3 )
28
39
bind = messages .MessageField (BindingMessage , 4 , repeated = True )
29
40
limit = messages .IntegerField (5 )
30
-
31
- def _parse_field (self , field ):
32
- if isinstance (field , resources .Asset ):
33
- return field .url
34
- elif isinstance (field , resources .Entry ):
35
- return field .sys ['id' ]
36
- elif isinstance (field , resources .ResourceLink ):
37
- return self .cda .resolve_resource_link (field )
38
- elif isinstance (field , list ):
39
- return [self ._parse_field (sub_field ) for sub_field in field ]
40
- return field
41
+ preview = messages .BooleanField (6 , default = False )
41
42
42
43
def _parse_entry (self , entry ):
43
44
"""Parses an entry from Contentful."""
@@ -63,48 +64,49 @@ def _parse_entry(self, entry):
63
64
body = body .encode ('utf-8' )
64
65
return fields , body , basename
65
66
66
- def bind_collection (self , entries , collection_pod_path , contentful_model ):
67
+ def bind_collection (self , entries , collection_pod_path ):
67
68
"""Binds a Grow collection to a Contentful collection."""
68
69
collection = self .pod .get_collection (collection_pod_path )
69
70
existing_pod_paths = [
70
71
doc .pod_path for doc in collection .list_docs (recursive = False , inject = False )]
71
72
new_pod_paths = []
72
73
for i , entry in enumerate (entries ):
73
- if entry .sys ['contentType' ]['sys' ]['id' ] != contentful_model :
74
- continue
75
- fields , body , basename = self ._parse_entry (entry )
76
- # TODO: Ensure `create_doc` doesn't die if the file doesn't exist.
77
- path = os .path .join (collection .pod_path , basename )
78
- if not self .pod .file_exists (path ):
79
- self .pod .write_yaml (path , {})
80
- doc = collection .create_doc (basename , fields = fields , body = body )
81
- new_pod_paths .append (doc .pod_path )
82
- self .pod .logger .info ('Saved -> {}' .format (doc .pod_path ))
74
+ result = json .dumps (entry .fields (), cls = self .encoder ())
75
+ print result
76
+
77
+ # if entry.sys['contentType']['sys']['id'] != contentful_model:
78
+ # continue
79
+ # fields, body, basename = self._parse_entry(entry)
80
+ # # TODO: Ensure `create_doc` doesn't die if the file doesn't exist.
81
+ # path = os.path.join(collection.pod_path, basename)
82
+ # if not self.pod.file_exists(path):
83
+ # self.pod.write_yaml(path, {})
84
+ # doc = collection.create_doc(basename, fields=fields, body=body)
85
+ # new_pod_paths.append(doc.pod_path)
86
+ # self.pod.logger.info('Saved -> {}'.format(doc.pod_path))
87
+
83
88
pod_paths_to_delete = set (existing_pod_paths ) - set (new_pod_paths )
84
89
for pod_path in pod_paths_to_delete :
85
90
self .pod .delete_file (pod_path )
86
91
self .pod .logger .info ('Deleted -> {}' .format (pod_path ))
87
92
88
93
def run (self , * args , ** kwargs ):
89
- request = self .cda .fetch (resources .Entry )
90
- if self .config .limit :
91
- request .params ['limit' ] = self .config .limit
92
- entries = request .all ()
93
94
for binding in self .config .bind :
94
- self .bind_collection (entries , binding .collection ,
95
- binding .contentModel )
95
+ content_type = binding .content_type
96
+ entries = self .client .entries ({
97
+ 'content_type' : content_type ,
98
+ })
99
+ self .bind_collection (entries , binding .collection )
96
100
97
101
@property
98
102
@utils .memoize
99
- def cda (self ):
103
+ def client (self ):
100
104
"""Contentful API client."""
101
- endpoint = None
102
- token = self .config .keys .production
103
- # Use preview endpoint if preview key is provided.
104
- if self .config .keys .preview :
105
- token = self .config .keys .preview
106
- endpoint = ContentfulPreprocessor ._preview_endpoint
107
- return client .Client (self .config .space , token , endpoint = endpoint )
105
+ access_token = self .config .access_token
106
+ if self .config .preview :
107
+ api_url = 'preview.contentful.com'
108
+ return contentful .Client (self .config .space , access_token , api_url = api_url )
109
+ return contentful .Client (self .config .space , access_token )
108
110
109
111
def can_inject (self , doc = None , collection = None ):
110
112
if not self .injected :
0 commit comments