From 1725d16f720291e6fd345035be1515e4f342b1e6 Mon Sep 17 00:00:00 2001 From: Rob Blau Date: Thu, 27 Jan 2011 14:37:26 -0800 Subject: [PATCH 1/2] Added support for update, delete, create, and batch calls. --- shotgun_api.mu | 221 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 203 insertions(+), 18 deletions(-) diff --git a/shotgun_api.mu b/shotgun_api.mu index 99bf1ae..af713f7 100644 --- a/shotgun_api.mu +++ b/shotgun_api.mu @@ -16,6 +16,64 @@ is an entity represented as an array of (name, Value) pairs -- i.e. the fields. """ +/* Example Use */ + +/* + +ShotgunServer sg = ShotgunServer(URL, SCRIPT, KEY); + +\: deleteCB(void; bool ret) { + print("DEBUG: DELETED: %s\n" % ret); +} + +\: updateCB(void; EntityFields fields) { + let descriptions = fields.extractStringField("description"), + ids = fields.extractIntField("id"); + print("DEBUG: DESCRIPTIONS: %s\n" % descriptions); + print("DEBUG: IDS: %s\n" % ids); + sg.delete("Playlist", ids[0]._1, deleteCB); +} + +\: createCB(void; EntityFields fields) { + let descriptions = fields.extractStringField("description"), + ids = fields.extractIntField("id"); + print("DEBUG: DESCRIPTIONS: %s\n" % descriptions); + print("DEBUG: IDS: %s\n" % ids); + let data = Struct([("description", String("description part two"))]); + sg.update("Playlist", ids[0]._1, data, updateCB); +} + +let data = Struct([("description", String("this is a description")), + ("code", String("Test")), + ("project", Struct([ + ("type", String("Project")), + ("id", Int(106)), + ])) + ]); + +sg.create("Playlist", data, nil, createCB); + +\: batchCB(void; Value responses) { + print("DEBUG: RESPONSES: %s\n" % responses); +} + +let requests = Array([ + Struct([ + ("request_type", String("create")), + ("entity_type", String("Playlist")), + ("data", Struct([ + ("code", String("Test 1")), + ("project", Struct([ + ("type", String("Project")), + ("id", Int(106)), + ])) + ])), + ])]); + +sg.batch(requests, batchCB); + +*/ + class: EntityFields { Field := (string, Value); @@ -84,6 +142,14 @@ class: EntityFields } deb ("totalPages %s totalEntities %s thisPage %s\n" % (_totalPages, _totalEntities, _thisPage)); } + else + if (member._0 == "id") + { + // No paging, entity returned directly + FieldArray fields = FieldArray(); + for_each (f; top) fields.push_back(f); + _entities.push_back(fields); + } } @@ -222,6 +288,8 @@ methods on this class are: class: ShotgunServer { EntityFieldsFunc := (void;EntityFields); + BoolFunc := (void; bool); + ValueFunc := (void; Value); string _url; string _script_name; @@ -248,6 +316,15 @@ class: ShotgunServer call("read", [queryParam], F); } + method: _convertStructToFields(Value; Value v) { + // convert data into a list of {"field_name": field, "value": value} structs + let Struct s = v; + [Value] fields; + for_each(p; s) + fields = Struct([("field_name", String(p._0)), ("value", p._1)]) : fields; + return Array(fields); + } + documentation: """ find() takes the name of an entity followed by a list of strings indicating fields you want reported. Next is a callback function which @@ -270,6 +347,7 @@ class: ShotgunServer EntityFieldsFunc Fcallback, int page, int numPerPage, + Value order, EntityFields[] responses, bool isRequest, Value responseValue) @@ -288,30 +366,23 @@ class: ShotgunServer ++count; } - let paging = Struct( [ ("paging", - Struct( [("current_page", Int(page)), - ("entities_per_page", Int(numPerPage))] )), - ("filters", filters), - ("type", String(entityType)) - ] ); - + let parts = [("paging", Struct([ + ("current_page", Int(page)), + ("entities_per_page", Int(numPerPage))])), + ("filters", filters), + ("type", String(entityType))]; if (0 != count) - { - paging = Struct( [ ("paging", - Struct( [("current_page", Int(page)), - ("entities_per_page", Int(numPerPage))] )), - ("filters", filters), - ("type", String(entityType)), - ("return_fields", Array(fieldList)) - ] ); - } + parts = ("return_fields", Array(fieldList)) : parts; + if (order neq nil) + parts = ("sorts", order) : parts; - callRead(paging, _doFind (entityType, + callRead(Struct(parts), _doFind (entityType, fields, filters, Fcallback, page, numPerPage, + order, responses, false,)); } @@ -348,6 +419,7 @@ class: ShotgunServer Fcallback, p, numPerPage, + order, responses, true, Nil); @@ -382,7 +454,8 @@ class: ShotgunServer EntityFieldsFunc Fcallback, Value filters = nil, int page = 1, - int numPerPage = 50) + int numPerPage = 50, + Value order = nil) { let myFilters = if (filters eq nil) then Struct( [("conditions", EmptyArray), ("logical_operator", String("and"))] ) else filters; @@ -393,11 +466,123 @@ class: ShotgunServer Fcallback, page, numPerPage, + order, EntityFields[](), true, Nil); } + method: create (void; string entityType, Value data, [string] fields, EntityFieldsFunc Fcallback) { + // convert fields into xmlrpc friendly Values + [Value] fieldList; + for_each(f; fields) + fieldList = String(f) : fieldList; + // build the actual xmlrpc argument + let args = Struct([ + ("type", String(entityType)), + ("fields", _convertStructToFields(data)), + ("return_fields", if(fields neq nil) then Array(fieldList) else Array([String("id")])), + ]); + // callback for response + \: _handleCreateResponse(void; Value responseValue) { + deb("_handleCreateResponse called: %s\n" % responseValue); + Fcallback(EntityFields(responseValue)); + commands.redraw(); + } + // do the call + call("create", [args], _handleCreateResponse); + } + + method: update(void; string entityType, int entityId, Value data, EntityFieldsFunc Fcallback) { + let args = Struct([ + ("type", String(entityType)), + ("id", Int(entityId)), + ("fields", _convertStructToFields(data)), + ]); + // callback for response + \: _handleUpdateResponse(void; Value responseValue) { + deb("_handleUpdateResponse called: %s\n" % responseValue); + Fcallback(EntityFields(responseValue)); + commands.redraw(); + } + // do the call + call("update", [args], _handleUpdateResponse); + } + + method: delete(void; string entityType, int entityId, BoolFunc Fcallback) { + let args = Struct([ + ("type", String(entityType)), + ("id", Int(entityId)), + ]); + // callback for response + \: _handleDeleteResponse(void; Value responseValue) { + deb("_handleDeleteResponse called: %s\n" % responseValue); + let Struct [ (_, Bool ret) ] = responseValue; + Fcallback(ret); + commands.redraw(); + } + // do the call + call("delete", [args], _handleDeleteResponse); + } + + method: batch(void; Value requests, ValueFunc Fcallback) { + [Value] myRequests; + case(requests) { + Array a -> { + for_each(p; a) { + let Struct request = p; + string requestType; + Value entityType; + Value entityId; + Value data; + Value returnFields; + for_each(q; request) { + case(q._0) { + "request_type" -> { let String temp = q._1; requestType = temp;} + "entity_type" -> { entityType = q._1; } + "entity_id" -> { entityId = q._1; } + "data" -> { data = q._1; } + "returnFields" -> { returnFields = q._1; } + } + } // end for_each(q, request) + + case(requestType) { + "create" -> { + let parts = [("request_type", String("create")), + ("type", entityType), + ("fields", _convertStructToFields(data))]; + if(returnFields neq nil) + parts = ("return_fields", returnFields) : parts; + myRequests = Struct(parts) : myRequests; + } "update" -> { + let arg = Struct([ + ("request_type", String("update")), + ("type", entityType), + ("id", entityId), + ("fields", _convertStructToFields(data))]); + myRequests = arg : myRequests; + } "delete" -> { + let arg = Struct([ + ("request_type", String("delete")), + ("type", entityType), + ("id", entityId)]); + myRequests = arg : myRequests; + } + } // end requestType case + } // end for_each(p, a) + } // end case Array a + } // end case(requests) + // callback for response + \: _handleBatchResponse(void; Value responseValue) { + deb("_handleBatchResponse called: %s\n" % responseValue); + // START HERE: Need a different callback type for batch returns + Fcallback(responseValue); + commands.redraw(); + } + // do the call + call("batch", [Array(myRequests)], _handleBatchResponse); + } + method: __test (void;) { \: printValues (void; EntityFields fields) From 4ec111fc74ae8240917ee32a4e75f92c0c09e49a Mon Sep 17 00:00:00 2001 From: Rob Blau Date: Tue, 21 Feb 2012 13:03:13 -0800 Subject: [PATCH 2/2] Updated to support multiple shotgun servers. --- shotgun_mode.mu | 21 ++++++++++++++++++--- shotgun_state.mu | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/shotgun_mode.mu b/shotgun_mode.mu index 4be70b1..03a383d 100644 --- a/shotgun_mode.mu +++ b/shotgun_mode.mu @@ -1068,15 +1068,30 @@ class: ShotgunMinorMode : MinorMode } } - method: sessionFromVersionIDs (void; int[] ids, bool doCompare = false, bool clearFirst = true) + method: sessionFromVersionIDs (void; int[] ids, bool doCompare = false, bool clearFirst = true, string flags="") { - deb ("shotgun mode sessionFromVersionIDs called\n"); + deb ("shotgun mode sessionFromVersionIDs(%s, %s, %s, %s) called\n" % (ids, doCompare, clearFirst, flags)); + StringMap flagMap = StringMap(7); + for_each (flag; flags.split(" ")) + { + string[] pair = flag.split("="); + flagMap.add(pair[0], pair[1]); + } + deb ("flagMap: %s\n" % flagMap.toString()); + State state = data(); if (0 == sources().size()) state.emptySessionStr = "Loading From Shotgun ..."; if (0 == ids.size()) return; - _shotgunState.collectVersionInfo(ids, sessionFromInfos(doCompare,clearFirst,)); + string serverUrl = ""; + try + { + serverUrl = "http://%s" % flagMap.find("serverUrl"); + } + catch (...) {;} + + _shotgunState.collectVersionInfo(ids, sessionFromInfos(doCompare,clearFirst,), serverUrl); } method: goToPage (void; string url) diff --git a/shotgun_state.mu b/shotgun_state.mu index 8fe2bce..3acd17b 100644 --- a/shotgun_state.mu +++ b/shotgun_state.mu @@ -89,7 +89,8 @@ class: ShotgunState ok = false; } - if (ok) this.connectToServer(); + // defer connecting to server until we know which server launched us + // if (ok) this.connectToServer(); } method: recordsReturnedLast(int;) @@ -162,12 +163,27 @@ class: ShotgunState } - method: connectToServer(void; ) + method: connectToServer(void; string serverUrl="") { try { - let (url, scriptKey) = lookupServer (_serverURL); + string lookup; + if (serverUrl == "") + { + // if we've already connected, then there is nothing to do + if (_shotgunServer neq nil) return; + lookup = _serverURL; + } + else + lookup = serverUrl; + let (url, scriptKey) = lookupServer (lookup); + + /* + * default url to connect to becomes last server passed in. + * this doesn't work great for sessions where entities come from different + * servers, but support for that is in the future + */ _serverURL = url; _scriptKey = scriptKey; if (url eq nil) throw exception ("ShotgunState: cannot connect to nil url"); @@ -406,7 +422,7 @@ class: ShotgunState else { deb (" nextEntity is %s, requesting info\n" % nextEntity); - _requestInfo (newTargetIDs, nextEntity, requestedEntities, infos, afterFunc); + _requestInfo (newTargetIDs, nextEntity, requestedEntities, infos, afterFunc, ""); } } catch (exception exc) @@ -496,11 +512,18 @@ class: ShotgunState string targetEntity, string[] requestedEntities, StringMap[] infos, - (void; StringMap[]) afterFunc) + (void; StringMap[]) afterFunc, + string serverUrl) { deb ("ShotgunState _requestInfo called\n"); deb (" targetIDs %s\n" % targetIDs); deb (" targetEntity %s\n" % targetEntity); + deb (" serverUrl %s\n" % serverUrl); + deb (" _serverURL %s\n" % _serverURL); + + // if we are trying to talk to a different shotgun server than the default + if (serverUrl != _serverURL) + connectToServer(serverUrl); _updateEmptySessionStr (targetEntity); @@ -535,17 +558,18 @@ class: ShotgunState ])); } - method: collectVersionInfo (void; int[] ids, (void; StringMap[]) afterFunc) + method: collectVersionInfo (void; int[] ids, (void; StringMap[]) afterFunc, string serverURL="") { deb ("ShotgunState collectVersionInfo called\n"); deb (" ids %s\n" % ids); + deb (" serverURL %s\n" % serverURL); if (0 == ids.size()) return; StringMap[] infos; for_each (id; ids) infos.push_back(shotgun_fields.freshInfo()); deb (" info[0] %s\n" % infos[0].toString(" ")); - _requestInfo (ids, "Version", string[](), infos, afterFunc); + _requestInfo (ids, "Version", string[](), infos, afterFunc, serverURL); } method: collectAllVersionInfo (void; (void; StringMap[]) afterFunc)