Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prediction: add promise support #1708

Merged
merged 1 commit into from
Oct 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions packages/prediction/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ model.query('Hello', function(err, results) {
// ]
}
});

// Promises are also supported by omitting callbacks.
model.query('Hello').then(function(data) {
var results = data[0];
});

// It's also possible to integrate with third-party Promise libraries.
var prediction = require('@google-cloud/prediction')({
promise: require('bluebird')
});
```


Expand Down
2 changes: 1 addition & 1 deletion packages/prediction/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"prediction"
],
"dependencies": {
"@google-cloud/common": "^0.6.0",
"@google-cloud/common": "^0.7.0",
"JSONStream": "^1.0.7",
"arrify": "^1.0.0",
"extend": "^3.0.0",
Expand Down
74 changes: 53 additions & 21 deletions packages/prediction/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,14 @@ util.inherits(Prediction, common.Service);
* prediction.createModel('my-model', {
* data: modelDataCsv
* }, function(err, model, apiResponse) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* prediction.createModel('my-model').then(function(data) {
* var model = data[0];
* var apiResponse = data[1];
* });
*/
Prediction.prototype.createModel = function(id, options, callback) {
var self = this;
Expand Down Expand Up @@ -219,25 +227,11 @@ Prediction.prototype.createModel = function(id, options, callback) {
* }, callback);
*
* //-
* // Get the models from your project as a readable object stream.
* // If the callback is omitted, we'll return a Promise.
* //-
* prediction.getModels()
* .on('error', console.error)
* .on('data', function(model) {
* // model is a Model object.
* })
* .on('end', function() {
* // All models retrieved.
* });
*
* //-
* // If you anticipate many results, you can end a stream early to prevent
* // unnecessary processing and API requests.
* //-
* prediction.getModels()
* .on('data', function(model) {
* this.end();
* });
* prediction.getModels().then(function(data) {
* var models = data[0];
* });
*/
Prediction.prototype.getModels = function(query, callback) {
var self = this;
Expand Down Expand Up @@ -274,6 +268,35 @@ Prediction.prototype.getModels = function(query, callback) {
});
};

/**
* Gets a list of {module:prediction/model} objects for the project as a
* readable object stream.
*
* @param {object=} query - Configuration object. See
* {module:prediction#getModels} for a complete list of options.
* @return {stream}
*
* @example
* prediction.getModelsStream()
* .on('error', console.error)
* .on('data', function(model) {
* // model is a Model object.
* })
* .on('end', function() {
* // All models retrieved.
* });
*
* //-
* // If you anticipate many results, you can end a stream early to prevent
* // unnecessary processing and API requests.
* //-
* prediction.getModelsStream()
* .on('data', function(model) {
* this.end();
* });
*/
Prediction.prototype.getModelsStream = common.paginator.streamify('getModels');

/**
* Create a model object representing a trained model.
*
Expand All @@ -295,10 +318,19 @@ Prediction.prototype.model = function(id) {

/*! Developer Documentation
*
* These methods can be used with either a callback or as a readable object
* stream. `streamRouter` is used to add this dual behavior.
* These methods can be auto-paginated.
*/
common.streamRouter.extend(Prediction, 'getModels');
common.paginator.extend(Prediction, 'getModels');

/*! Developer Documentation
*
* All async methods (except for streams) will return a Promise in the event
* that a callback is omitted.
*/
common.util.promisifyAll(Prediction, {
exclude: ['model']
});


Prediction.Model = Model;

Expand Down
77 changes: 76 additions & 1 deletion packages/prediction/src/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ function Model(prediction, id) {
* // The model was created successfully.
* }
* });
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* model.create().then(function(data) {
* var model = data[0];
* var apiResponse = data[1];
* });
*/
create: true,

Expand All @@ -75,6 +83,13 @@ function Model(prediction, id) {
*
* @example
* model.delete(function(err, apiResponse) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* model.delete().then(function(data) {
* var apiResponse = data[0];
* });
*/
delete: true,

Expand All @@ -88,6 +103,13 @@ function Model(prediction, id) {
*
* @example
* model.exists(function(err, exists) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* model.exists().then(function(data) {
* var exists = data[0];
* });
*/
exists: true,

Expand All @@ -107,6 +129,14 @@ function Model(prediction, id) {
* model.get(function(err, model, apiResponse) {
* // `model.metadata` has been populated.
* });
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* model.get().then(function(data) {
* var model = data[0];
* var apiResponse = data[1];
* });
*/
get: true,

Expand All @@ -122,6 +152,14 @@ function Model(prediction, id) {
*
* @example
* model.getMetadata(function(err, metadata, apiResponse) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* model.getMetadata().then(function(data) {
* var metadata = data[0];
* var apiResponse = data[1];
* });
*/
getMetadata: true,

Expand All @@ -148,6 +186,13 @@ function Model(prediction, id) {
* };
*
* model.setMetadata(metadata, function(err, apiResponse) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* model.setMetadata(metadata).then(function(data) {
* var apiResponse = data[0];
* });
*/
setMetadata: {
reqOpts: {
Expand Down Expand Up @@ -188,6 +233,14 @@ util.inherits(Model, common.ServiceObject);
* // `analysis.model` == {...}
* }
* });
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* model.analyze().then(function(data) {
* var analysis = data[0];
* var apiResponse = data[1];
* });
*/
Model.prototype.analyze = function(callback) {
this.request({
Expand Down Expand Up @@ -241,7 +294,7 @@ Model.prototype.createWriteStream = function(label) {
csvInstance: [[]]
}).split('[]');

var requestStream = self.request({
var requestStream = self.requestStream({
method: 'PUT',
uri: '',
headers: {
Expand Down Expand Up @@ -312,6 +365,14 @@ Model.prototype.createWriteStream = function(label) {
* // ]
* }
* });
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* model.query('Hello').then(function(data) {
* var results = data[0];
* var apiResponse = data[1];
* });
*/
Model.prototype.query = function(input, callback) {
this.request({
Expand Down Expand Up @@ -365,6 +426,13 @@ Model.prototype.query = function(input, callback) {
* // New data was inserted successfully.
* }
* });
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* model.train('english', 'Hello from Stephen!').then(function(data) {
* var apiResponse = data[0];
* });
*/
Model.prototype.train = function(label, input, callback) {
this.setMetadata({
Expand All @@ -373,4 +441,11 @@ Model.prototype.train = function(label, input, callback) {
}, callback);
};

/*! Developer Documentation
*
* All async methods (except for streams) will return a Promise in the event
* that a callback is omitted.
*/
common.util.promisifyAll(Model);

module.exports = Model;
2 changes: 1 addition & 1 deletion packages/prediction/system-test/prediction.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ describe('Prediction', function() {
});

it('should return models in stream mode', function(done) {
prediction.getModels({ maxResults: 1 })
prediction.getModelsStream({ maxResults: 1 })
.on('error', done)
.once('data', function() {
done();
Expand Down
29 changes: 24 additions & 5 deletions packages/prediction/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function FakeService() {
nodeutil.inherits(FakeService, Service);

var extended = false;
var fakeStreamRouter = {
var fakePaginator = {
extend: function(Class, methods) {
if (Class.name !== 'Prediction') {
return;
Expand All @@ -46,12 +46,23 @@ var fakeStreamRouter = {
methods = arrify(methods);
assert.equal(Class.name, 'Prediction');
assert.deepEqual(methods, ['getModels']);
},
streamify: function(methodName) {
return methodName;
}
};


var promisified = false;
var fakeUtil = extend({}, util, {
makeAuthenticatedRequestFactory: util.noop
makeAuthenticatedRequestFactory: util.noop,
promisifyAll: function(Class, options) {
if (Class.name !== 'Prediction') {
return;
}

promisified = true;
assert.deepEqual(options.exclude, ['model']);
}
});

describe('Prediction', function() {
Expand All @@ -64,7 +75,7 @@ describe('Prediction', function() {
Prediction = proxyquire('../', {
'@google-cloud/common': {
Service: FakeService,
streamRouter: fakeStreamRouter,
paginator: fakePaginator,
util: fakeUtil
},
'./model.js': FakeModel,
Expand All @@ -79,7 +90,15 @@ describe('Prediction', function() {

describe('instantiation', function() {
it('should extend the correct methods', function() {
assert(extended); // See `fakeStreamRouter.extend`
assert(extended); // See `fakePaginator.extend`
});

it('should streamify the correct methods', function() {
assert.strictEqual(prediction.getModelsStream, 'getModels');
});

it('should promisify all the things', function() {
assert(promisified);
});

it('should normalize the arguments', function() {
Expand Down
Loading