Merge lp:~xavi-garcia-mena/go-unityscopes/list-all-scopes-metadata into lp:go-unityscopes/v2

Proposed by Xavi Garcia
Status: Merged
Approved by: James Henstridge
Approved revision: 72
Merged at revision: 69
Proposed branch: lp:~xavi-garcia-mena/go-unityscopes/list-all-scopes-metadata
Merge into: lp:go-unityscopes/v2
Diff against target: 252 lines (+148/-0)
8 files modified
export_test.go (+13/-0)
metadata.cpp (+10/-0)
metadata.go (+43/-0)
metadata_test.go (+27/-0)
shim.cpp (+15/-0)
shim.h (+6/-0)
tests/goscope/goscope.go (+12/-0)
unityscope.go (+22/-0)
To merge this branch: bzr merge lp:~xavi-garcia-mena/go-unityscopes/list-all-scopes-metadata
Reviewer Review Type Date Requested Status
James Henstridge Approve
Review via email: mp+259629@code.launchpad.net

Commit message

I've added the ScopeMetadata to the go-bindings in order to implement the method that lists all the existing scopes in the registry. ListRegistryScopes() in ScopeBase.

Description of the change

I've added the ScopeMetadata to the go-bindings in order to implement the method that lists all the existing scopes in the registry. ListRegistryScopes() in ScopeBase.

The idea would be to keep a pointer to the C++ ScopeMetadata when we need it to implement "find_child_scopes" as there is no way to create a new instance of the C++ ScopeMetadata using the public API. The C++ ScopeMetadata holds a pointer to the Middleware.

For the rest of attributes of ScopeMetadata I've created a copy in the go space to avoid making a C_go call every time we need to query for something.

This would be the base for the rest of the implementation for supporting aggregated scopes, so I'm moving to MP so it gets reviewed first.

There is a very basic test on the test scope that prints out the metadata obtained to stdout. That test should be removed when we have a more reliable way of testing this (using scope-harness possibly).

The idea would be to add next the ChildScope class, which holds the ScopeMetadata along with other attributes and implement the "clild_scopes" method in ScopeBase as well as the "find_child_scopes"

To post a comment you must log in.
70. By Xavi Garcia

Changed shared_ptr to ScopeMetadata to raw pointers

Revision history for this message
James Henstridge (jamesh) wrote :

This looks pretty good. I've left a few inline comments for some small issues I noticed. It looks like you're on the right track.

review: Needs Fixing
71. By Xavi Garcia

Added suggested changes

Revision history for this message
Xavi Garcia (xavi-garcia-mena) wrote :

Thanks for the review.

I've also left inline comments.

72. By Xavi Garcia

Added Keywords to ScopeMetadata

Revision history for this message
James Henstridge (jamesh) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'export_test.go'
2--- export_test.go 2015-03-02 05:41:40 +0000
3+++ export_test.go 2015-05-21 14:58:20 +0000
4@@ -1,7 +1,20 @@
5 package scopes
6
7+import (
8+ "encoding/json"
9+)
10+
11 // This file exports certain private functions for use by tests.
12
13 func NewTestingResult() *Result {
14 return newTestingResult()
15 }
16+
17+func NewTestingScopeMetadata(json_data string) ScopeMetadata {
18+ var scopeMetadata ScopeMetadata
19+ if err := json.Unmarshal([]byte(json_data), &scopeMetadata); err != nil {
20+ panic(err)
21+ }
22+
23+ return scopeMetadata
24+}
25
26=== modified file 'metadata.cpp'
27--- metadata.cpp 2015-04-17 09:54:06 +0000
28+++ metadata.cpp 2015-05-21 14:58:20 +0000
29@@ -4,6 +4,7 @@
30
31 #include <unity/scopes/ActionMetadata.h>
32 #include <unity/scopes/SearchMetadata.h>
33+#include <unity/scopes/ScopeMetadata.h>
34 #include <unity/scopes/ScopeExceptions.h>
35
36 extern "C" {
37@@ -173,3 +174,12 @@
38 }
39 return as_bytes(Variant(hints).serialize_json(), length);
40 }
41+
42+char *get_scope_metadata_serialized(_ScopeMetadata *metadata) {
43+ ScopeMetadata const*api_metadata = reinterpret_cast<ScopeMetadata const*>(metadata);
44+ return strdup(Variant(api_metadata->serialize()).serialize_json().c_str());
45+}
46+
47+void destroy_scope_metadata_ptr(_ScopeMetadata *metadata) {
48+ delete reinterpret_cast<ScopeMetadata*>(metadata);
49+}
50
51=== modified file 'metadata.go'
52--- metadata.go 2015-04-17 09:54:06 +0000
53+++ metadata.go 2015-05-21 14:58:20 +0000
54@@ -264,3 +264,46 @@
55 RegionName string `json:"region_name"`
56 ZipPostalCode string `json:"zip_postal_code"`
57 }
58+
59+type ProxyScopeMetadata struct {
60+ Identity string `json:"identity"`
61+ EndPoint string `json:"endpoint"`
62+}
63+
64+// ScopeMetadata holds scope attributes such as name, description, icon etc.
65+//
66+// The information stored by ScopeMetadata comes from the .ini file for the given scope (for local scopes)
67+// or is fetched from the remote server (for scopes running on Smart Scopes Server).
68+// Use ListRegistryScopes from ScopeBase to get the metadata for all scopes.
69+type ScopeMetadata struct {
70+ m *C._ScopeMetadata
71+ Art string `json:"art"`
72+ Author string `json:"author"`
73+ Description string `json:"description"`
74+ DisplayName string `json:"display_name"`
75+ Icon string `json:"icon"`
76+ Invisible bool `json:"invisible"`
77+ IsAggregator bool `json:"is_aggregator"`
78+ LocationDataNeeded bool `json:"location_data_needed"`
79+ ScopeDir string `json:"scope_dir"`
80+ ScopeId string `json:"scope_id"`
81+ Version int `json:"version"`
82+ Proxy ProxyScopeMetadata `json:"proxy"`
83+ AppearanceAttributes map[string]interface{} `json:"appearance_attributes"`
84+ SettingsDefinitions []interface{} `json:"settings_definitions"`
85+ Keywords []string `json:"keywords"`
86+}
87+
88+func finalizeScopeMetadata(metadata *ScopeMetadata) {
89+ C.destroy_scope_metadata_ptr(metadata.m)
90+}
91+
92+func makeScopeMetadata(m *C._ScopeMetadata, json_data string) *ScopeMetadata {
93+ metadata := new(ScopeMetadata)
94+ if err := json.Unmarshal([]byte(json_data), &metadata); err != nil {
95+ panic(err)
96+ }
97+ metadata.m = m
98+ runtime.SetFinalizer(metadata, finalizeScopeMetadata)
99+ return metadata
100+}
101
102=== modified file 'metadata_test.go'
103--- metadata_test.go 2015-04-17 09:54:06 +0000
104+++ metadata_test.go 2015-05-21 14:58:20 +0000
105@@ -146,3 +146,30 @@
106 c.Assert(err, Not(Equals), nil)
107 c.Check(err.Error(), Equals, "json: error calling MarshalJSON for type *scopes_test.unserializable: Can not marshal to JSON")
108 }
109+
110+func (s *S) TestScopeMetadataCreation(c *C) {
111+ json_data := "{\"appearance_attributes\":{\"page-header\":{\"background\":\"color:///#ffffff\",\"divider-color\":\"#b31217\",\"logo\":\"unity-scope-youtube/build/src/logo.png\"}},\"art\":\"unity-scope-youtube/build/src/screenshot.jpg\",\"author\":\"Canonical Ltd.\",\"description\":\"Search YouTube for videos and browse channels\",\"display_name\":\"YouTube\",\"icon\":\"unity-scope-youtube/build/src/icon.png\",\"invisible\":false,\"is_aggregator\":false,\"location_data_needed\":true,\"proxy\":{\"endpoint\":\"ipc:///tmp/scope-dev-endpoints.V4gbrE/priv/com.ubuntu.scopes.youtube_youtube\",\"identity\":\"com.ubuntu.scopes.youtube_youtube\"},\"scope_dir\":\"unity-scope-youtube/build/src\",\"scope_id\":\"com.ubuntu.scopes.youtube_youtube\",\"settings_definitions\":[{\"defaultValue\":true,\"displayName\":\"Enable location data\",\"id\":\"internal.location\",\"type\":\"boolean\"}],\"version\":0,\"keywords\":[\"music\",\"video\"]}"
112+
113+ scopeMetadata := scopes.NewTestingScopeMetadata(json_data)
114+ c.Assert(scopeMetadata, Not(Equals), nil)
115+
116+ c.Check(scopeMetadata.Art, Equals, "unity-scope-youtube/build/src/screenshot.jpg")
117+ c.Check(scopeMetadata.Author, Equals, "Canonical Ltd.")
118+ c.Check(scopeMetadata.Description, Equals, "Search YouTube for videos and browse channels")
119+ c.Check(scopeMetadata.DisplayName, Equals, "YouTube")
120+ c.Check(scopeMetadata.Icon, Equals, "unity-scope-youtube/build/src/icon.png")
121+ c.Check(scopeMetadata.Invisible, Equals, false)
122+ c.Check(scopeMetadata.IsAggregator, Equals, false)
123+ c.Check(scopeMetadata.LocationDataNeeded, Equals, true)
124+ c.Check(scopeMetadata.ScopeDir, Equals, "unity-scope-youtube/build/src")
125+ c.Check(scopeMetadata.ScopeId, Equals, "com.ubuntu.scopes.youtube_youtube")
126+ c.Check(scopeMetadata.Version, Equals, 0)
127+ c.Check(scopeMetadata.Proxy, Equals, scopes.ProxyScopeMetadata{"com.ubuntu.scopes.youtube_youtube", "ipc:///tmp/scope-dev-endpoints.V4gbrE/priv/com.ubuntu.scopes.youtube_youtube"})
128+ pageHeader, ok := scopeMetadata.AppearanceAttributes["page-header"].(map[string]interface{})
129+ c.Check(ok, Equals, true)
130+ c.Check(pageHeader["background"], Equals, "color:///#ffffff")
131+ c.Check(pageHeader["divider-color"], Equals, "#b31217")
132+ c.Check(pageHeader["logo"], Equals, "unity-scope-youtube/build/src/logo.png")
133+
134+ c.Check(scopeMetadata.Keywords, DeepEquals, []string{"music","video"})
135+}
136
137=== modified file 'shim.cpp'
138--- shim.cpp 2015-03-19 14:23:43 +0000
139+++ shim.cpp 2015-05-21 14:58:20 +0000
140@@ -51,3 +51,18 @@
141 destroy_ptr<const Category>(data);
142 }
143
144+_ScopeMetadata** list_registry_scopes_metadata(_ScopeBase *scope, int *n_scopes) {
145+ ScopeBase *s = reinterpret_cast<ScopeBase*>(scope);
146+ auto registry = s->registry();
147+ auto scopes = registry->list();
148+
149+ *n_scopes = scopes.size();
150+
151+ _ScopeMetadata** ret_data = reinterpret_cast<_ScopeMetadata**>(calloc(*n_scopes, sizeof(_ScopeMetadata*)));
152+ int i = 0;
153+ for( auto item: scopes ) {
154+ ret_data[i++] = reinterpret_cast<_ScopeMetadata*>(new ScopeMetadata(item.second));
155+ }
156+
157+ return ret_data;
158+}
159
160=== modified file 'shim.h'
161--- shim.h 2015-04-17 09:54:06 +0000
162+++ shim.h 2015-05-21 14:58:20 +0000
163@@ -16,6 +16,7 @@
164 typedef struct _Result _CategorisedResult;
165 typedef struct _SearchMetadata _SearchMetadata;
166 typedef struct _ActionMetadata _ActionMetadata;
167+typedef struct _ScopeMetadata _ScopeMetadata;
168 typedef struct _QueryMetadata _QueryMetadata;
169 typedef struct _ColumnLayout _ColumnLayout;
170 typedef void _ScopeBase;
171@@ -32,6 +33,7 @@
172 char *scope_base_cache_directory(_ScopeBase *scope);
173 char *scope_base_tmp_directory(_ScopeBase *scope);
174 void *scope_base_settings(_ScopeBase *scope, int *length);
175+_ScopeMetadata **list_registry_scopes_metadata(_ScopeBase *scope, int *n_scopes);
176
177 /* SearchReply objects */
178 void init_search_reply_ptr(SharedPtrData dest, SharedPtrData src);
179@@ -118,6 +120,10 @@
180 void *action_metadata_get_hint(_ActionMetadata *metadata, void *key, int *data_length, char **error);
181 void *action_metadata_get_hints(_ActionMetadata *metadata, int *length);
182
183+/* ScopeMetadata objects */
184+void destroy_scope_metadata_ptr(_ScopeMetadata *metadata);
185+char *get_scope_metadata_serialized(_ScopeMetadata *metadata);
186+
187 /* ActivationResponse objects */
188 void activation_response_init_status(_ActivationResponse *response, int status);
189 void activation_response_init_query(_ActivationResponse *response, _CannedQuery *query);
190
191=== modified file 'tests/goscope/goscope.go'
192--- tests/goscope/goscope.go 2015-03-30 10:11:02 +0000
193+++ tests/goscope/goscope.go 2015-05-21 14:58:20 +0000
194@@ -3,6 +3,7 @@
195 import (
196 "launchpad.net/go-unityscopes/v2"
197 "log"
198+ "fmt"
199 )
200
201 const searchCategoryTemplate = `{
202@@ -107,6 +108,17 @@
203
204 func (s *MyScope) SetScopeBase(base *scopes.ScopeBase) {
205 s.base = base
206+
207+ // THIS IS JUST A TEST ON THE STDOUT
208+ listScopes := s.base.ListRegistryScopes()
209+ fmt.Print("LIST SCOPES ****************************************************************\n")
210+ for k := range listScopes {
211+ fmt.Print(k)
212+ fmt.Print("\n")
213+ fmt.Print(*listScopes[k])
214+ fmt.Print("\n")
215+ }
216+ fmt.Print("LIST SCOPES ****************************************************************\n")
217 }
218
219 // RESULTS *********************************************************************
220
221=== modified file 'unityscope.go'
222--- unityscope.go 2015-03-25 10:18:56 +0000
223+++ unityscope.go 2015-05-21 14:58:20 +0000
224@@ -164,6 +164,28 @@
225 return C.GoString(dir)
226 }
227
228+// ListRegistryScopes lists all the scopes existing in the registry
229+func (b *ScopeBase) ListRegistryScopes() map[string]*ScopeMetadata {
230+ var nb_scopes C.int
231+ var c_array **C._ScopeMetadata = C.list_registry_scopes_metadata(b.b, &nb_scopes)
232+ defer C.free(unsafe.Pointer(c_array))
233+
234+ length := int(nb_scopes)
235+ // create a very big slice and then slice it to the number of scopes metadata
236+ slice := (*[1 << 27]*C._ScopeMetadata)(unsafe.Pointer(c_array))[:length:length]
237+ var scopesList = make(map[string]*ScopeMetadata)
238+
239+ for i := 0; i < length; i++ {
240+ json_data := C.get_scope_metadata_serialized(slice[i])
241+ defer C.free(unsafe.Pointer(json_data))
242+
243+ metadata := makeScopeMetadata(slice[i], C.GoString(json_data))
244+ scopesList[metadata.ScopeId] = metadata
245+ }
246+
247+ return scopesList
248+}
249+
250 // Settings returns the scope's settings. The settings will be
251 // decoded into the given value according to the same rules used by
252 // json.Unmarshal().

Subscribers

People subscribed via source and target branches

to all changes: