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

Add Code Examples #18

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
82 changes: 82 additions & 0 deletions examples/cancelTasks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
const scaleapi = require('../lib/scaleapi.js'); // Change to just "scaleapi" for your project
shaun-scale marked this conversation as resolved.
Show resolved Hide resolved
const fs = require('fs');

// HOW IT WORKS:
// Given a .csv file or array of task ids you'd like cancelled,
// go through and cancel Tasks for each row.

// INPUT PARAMETERS:
const API_KEY = 'live_xxxxx';
const DO_DRY_RUN = true;
const fileName = 'list/of/task/ids_to_cancel.csv'

const client = scaleapi.ScaleClient(API_KEY);

(async function () {
// ====================
// === READ IN ROWS ===
// ====================

// Read in Task Details from CSV
let rows = getIdsFromCsv(fileName);

// Alternatively, create just an array of rows to cancel Tasks from
// let rows = [
// '5d4121900591c138750xxxxx'
// ]

// ====================
// === PROCESS ROWS ===
// ====================

// Process each row as needed
rows = rows.map(
row => row.split(',')[0].trim()
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would make more sense for splitting by ',' should be handled by readCsv()

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to use a csv library. split(',') fails when you have string values that contain commas 😉

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point - csv-parse is a good one that I use in my own scripts!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the logic a bit to handle this better, I'd like to try and not add any more packages to the package.json beyond request and I don't think fancy .csv handling is worth the extra dev hassle to get value from this script. If it's cool with you guys, I'll leave my little helper function here instead of doing the fully correct solution.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't agree with that. You're providing a csv parser that doesn't handle edge cases. Why does the example need CSV? Why not just use a text file with task ids on new lines? I would also expect any service or API we provide to correctly handle input validation (e.g., testing id string length).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll go with the .txt file approach, that seems really reasonable.

I think somewhere else I had input validation, I'll add that here as well.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I meant the API side should handle it so the customers shouldn't have to worry about it


console.log(`Number of Rows Found: ${rows.length}`);

// ====================
// === CANCEL TASKS ===
// ====================

if (rows.length > 0) {
shaun-scale marked this conversation as resolved.
Show resolved Hide resolved
await Promise.map(
rows,
async row => {
if (DO_DRY_RUN) {
console.log('Would be cancelling Task Id: ' + row);
} else {
await new Promise((resolve, reject) => {
client.cancelTask(row, (err, task) => {
// do something with task
if (err) {
console.error(err);
reject(err);
} else {
console.log(`Task Cancelled: ${task.task_id}`);
resolve();
}
});
});
}
},
{ concurrency: 10 },
);

console.log('Finished Running Script');
}
}());

let readCsv = function(fileName, hasHeader = false) {
const rows =
fs.readFileSync(fileName, { encoding: 'utf8' })
.split('\n')
.map(s => s.trim()) || [];

return hasHeader && rows.length > 0 ? rows.splice(1) : rows;
}

let getIdsFromCsv = function(fileName, hasHeader) {
return readCsv(fileName, hasHeader).filter(s => s.length === 24);
};
89 changes: 89 additions & 0 deletions examples/createNewTasks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
const scaleapi = require('../lib/scaleapi.js'); // Change to just "scaleapi" for your project
const fs = require('fs');

// HOW IT WORKS:
// Given a .csv file or array of information to make tasks from (often attachment urls),
// go through and submit Tasks to Scale for each row.

// You will want to specify which task creation method you'd like to use, as well as
// any input parameters relating to how you'd like your task completed

// INPUT PARAMETERS:
const API_KEY = 'live_xxxxx';
const DO_DRY_RUN = true;
shaun-scale marked this conversation as resolved.
Show resolved Hide resolved
const fileName = 'list/of/attachment_urls_and_other_data.csv'

const client = scaleapi.ScaleClient(API_KEY);

(async function () {
// ====================
// === READ IN ROWS ===
// ====================

// Read in Task Details from CSV
let rows = readCsv(fileName);

// Alternatively, create just an array of rows to create Tasks from
// let rows = [
// 'https://www.scale.com/img/is/awesome.jpg'
// ]

// ====================
// === PROCESS ROWS ===
// ====================

// Process each row as needed
rows = rows.map(row => row.split(',')[0].trim());
shaun-scale marked this conversation as resolved.
Show resolved Hide resolved

console.log(`Number of Rows Found: ${rows.length}`);

// ====================
// === CREATE TASKS ===
// ====================

if (rows.length > 0) {
await Promise.map(
rows,
async row => {
if (DO_DRY_RUN) {
console.log('Creating Task for ' + row);
} else {
await new Promise((resolve, reject) => {
client.createAnnotationTask(
{
callback_url: 'http://www.example.com/callback',
project: 'coolest_project_name',
objects_to_annotate: ['person', 'land vehicle'],
with_labels: true,
attachment: row,
attachment_type: 'image',
},
(err, task) => {
// do something with task
if (err) {
console.error(err);
reject(err);
} else {
console.log(`Task Created: ${task.task_id}`);
resolve();
}
},
);
});
}
},
{ concurrency: 5 },
);

console.log('Finished Running Script');
}
}());

function readCsv(fileName, hasHeader = false) {
const rows =
fs.readFileSync(fileName, { encoding: 'utf8' })
.split('\n')
.map(s => s.trim()) || [];

return hasHeader && rows.length > 0 ? rows.splice(1) : rows;
shaun-scale marked this conversation as resolved.
Show resolved Hide resolved
}
84 changes: 84 additions & 0 deletions examples/getAllTasks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
const scaleapi = require('../lib/scaleapi.js'); // Change to just "scaleapi" for your project
const fs = require('fs');

// HOW IT WORKS:
// Given a list of search filters ("PARAMS"), it will page through tasks and write
// the output to a JSON file.


// INPUT PARAMETERS:
const API_KEY = 'live_xxxxx';

const MAX_TASKS_TO_RETURN = 100000; // Get up to the n most recently created tasks

const OUTPUT_FILE = '/the/place/to/put/it.json';
shaun-scale marked this conversation as resolved.
Show resolved Hide resolved

const PARAMS = { // All params optional
type: 'annotation',
status: 'completed',
project: 'cool_project_name',
completed_after: '2019-03-01T00:00:00.000Z'
};

(async function () {

// ===============================
// == MAIN FUNCTION WE CAN CALL ==
// ===============================

// Get list of task objects
let getTasks = async function(client, maxTasksToReturn = 1000000, params = {}) {
// Initialize everything
const maxTasksReturnedPerCall = 100;
shaun-scale marked this conversation as resolved.
Show resolved Hide resolved
let lastPageCount = maxTasksReturnedPerCall;
let output = [];

// Go through page by page
while (lastPageCount == maxTasksReturnedPerCall && output.length < maxTasksToReturn) {
shaun-scale marked this conversation as resolved.
Show resolved Hide resolved

// Skip ahead (offset) by the number of tasks already pulled
params.offset = output.length;
shaun-scale marked this conversation as resolved.
Show resolved Hide resolved

// Support asking for small number of tasks (like 5, 10, 50)
params.limit = maxTasksReturnedPerCall;
if (maxTasksToReturn - output.length < maxTasksReturnedPerCall) {
params.limit = maxTasksToReturn - output.length
}

try {
// fetch some tasks
let tasks = await new Promise((resolve, reject) => {
client.tasks(params, (err, tasklist) => {
if (err) {
console.error(err);
reject(err);
} else {
resolve(tasklist);
}
});
});

// concat with output
output = output.concat(tasks.docs);
lastPageCount = tasks.docs.length;

console.log(`Fetched ${output.length} tasks`);
} catch(err) {
console.error(err)
}
}

console.log(`Finished fetching ${output.length} tasks`);

return output;
}

// ============================
// == CALL OUR MAIN FUNCTION ==
// ============================

const client = new scaleapi.ScaleClient(API_KEY);
let tasks = await getTasks(client, MAX_TASKS_TO_RETURN, PARAMS);
fs.writeFileSync(OUTPUT_FILE, JSON.stringify(tasks));
}());