diff --git a/circle.yml b/circle.yml index 25b53c8ca54..e69de29bb2d 100644 --- a/circle.yml +++ b/circle.yml @@ -1,28 +0,0 @@ -## Customize the test machine (pass) - -## Customize checkout -checkout: - post: - - git submodule sync - - git submodule update --init # use submodules - -## Customize dependencies -dependencies: - post: - - pip install -I . - - cd ~ && python -c "import plotly" - - pip install matplotlib - -## Customize database setup (pass) - -## Customize test commands -test: - post: - - nosetests -w plotly/tests/test_optional - - pip uninstall -y matplotlib - - nosetests -w plotly/tests/test_core - - chmod 000 ~/.plotly && python -c "import plotly" - -## Customize deployment commands (pass) - -## Custom notifications (pass) \ No newline at end of file diff --git a/make_instructions.txt b/make_instructions.txt index 03fa1484d96..b789f2a62e9 100644 --- a/make_instructions.txt +++ b/make_instructions.txt @@ -38,8 +38,6 @@ Available targets (i.e. $ make target): pull_refs -> pull in graph_reference *master* branch - make_coverage -> (requires `nose` and `coverage`) run tests with coverage - ################################################################################ Getting setup: diff --git a/makefile b/makefile index e72f5af8918..aa5a9447399 100644 --- a/makefile +++ b/makefile @@ -59,14 +59,3 @@ pull_chunked : submodules/chunked_requests @echo "" @echo "Pulling down updates from chunked_requests" cd submodules/chunked_requests; git pull origin master - -run_coverage : - @echo "" - @echo "Running api nosetests with coverage" - nosetests -w plotly/tests --with-coverage --cover-erase --cover-package plotly.plotly.plotly --cover-package plotly.graph_objs.graph_objs --cover-package plotly.graph_objs.graph_objs_tools --cover-package plotly.matplotlylib.mpltools --cover-package plotly.matplotlylib.renderer --cover-package plotly.tools --cover-package plotly.exceptions --cover-package plotly.utils --cover-package plotly.version - @echo "Removing old html if it exists" - if [ -d plotly/tests/coverage ]; then rm -rf plotly/tests/coverage; fi - @echo "Generating html with coverage" - coverage html -d plotly/tests/coverage - - diff --git a/plotly/tests/coverage/coverage_html.js b/plotly/tests/coverage/coverage_html.js deleted file mode 100644 index b24006d25e0..00000000000 --- a/plotly/tests/coverage/coverage_html.js +++ /dev/null @@ -1,376 +0,0 @@ -// Coverage.py HTML report browser code. -/*jslint browser: true, sloppy: true, vars: true, plusplus: true, maxerr: 50, indent: 4 */ -/*global coverage: true, document, window, $ */ - -coverage = {}; - -// Find all the elements with shortkey_* class, and use them to assign a shotrtcut key. -coverage.assign_shortkeys = function () { - $("*[class*='shortkey_']").each(function (i, e) { - $.each($(e).attr("class").split(" "), function (i, c) { - if (/^shortkey_/.test(c)) { - $(document).bind('keydown', c.substr(9), function () { - $(e).click(); - }); - } - }); - }); -}; - -// Create the events for the help panel. -coverage.wire_up_help_panel = function () { - $("#keyboard_icon").click(function () { - // Show the help panel, and position it so the keyboard icon in the - // panel is in the same place as the keyboard icon in the header. - $(".help_panel").show(); - var koff = $("#keyboard_icon").offset(); - var poff = $("#panel_icon").position(); - $(".help_panel").offset({ - top: koff.top-poff.top, - left: koff.left-poff.left - }); - }); - $("#panel_icon").click(function () { - $(".help_panel").hide(); - }); -}; - -// Loaded on index.html -coverage.index_ready = function ($) { - // Look for a cookie containing previous sort settings: - var sort_list = []; - var cookie_name = "COVERAGE_INDEX_SORT"; - var i; - - // This almost makes it worth installing the jQuery cookie plugin: - if (document.cookie.indexOf(cookie_name) > -1) { - var cookies = document.cookie.split(";"); - for (i = 0; i < cookies.length; i++) { - var parts = cookies[i].split("="); - - if ($.trim(parts[0]) === cookie_name && parts[1]) { - sort_list = eval("[[" + parts[1] + "]]"); - break; - } - } - } - - // Create a new widget which exists only to save and restore - // the sort order: - $.tablesorter.addWidget({ - id: "persistentSort", - - // Format is called by the widget before displaying: - format: function (table) { - if (table.config.sortList.length === 0 && sort_list.length > 0) { - // This table hasn't been sorted before - we'll use - // our stored settings: - $(table).trigger('sorton', [sort_list]); - } - else { - // This is not the first load - something has - // already defined sorting so we'll just update - // our stored value to match: - sort_list = table.config.sortList; - } - } - }); - - // Configure our tablesorter to handle the variable number of - // columns produced depending on report options: - var headers = []; - var col_count = $("table.index > thead > tr > th").length; - - headers[0] = { sorter: 'text' }; - for (i = 1; i < col_count-1; i++) { - headers[i] = { sorter: 'digit' }; - } - headers[col_count-1] = { sorter: 'percent' }; - - // Enable the table sorter: - $("table.index").tablesorter({ - widgets: ['persistentSort'], - headers: headers - }); - - coverage.assign_shortkeys(); - coverage.wire_up_help_panel(); - - // Watch for page unload events so we can save the final sort settings: - $(window).unload(function () { - document.cookie = cookie_name + "=" + sort_list.toString() + "; path=/"; - }); -}; - -// -- pyfile stuff -- - -coverage.pyfile_ready = function ($) { - // If we're directed to a particular line number, highlight the line. - var frag = location.hash; - if (frag.length > 2 && frag[1] === 'n') { - $(frag).addClass('highlight'); - coverage.set_sel(parseInt(frag.substr(2), 10)); - } - else { - coverage.set_sel(0); - } - - $(document) - .bind('keydown', 'j', coverage.to_next_chunk_nicely) - .bind('keydown', 'k', coverage.to_prev_chunk_nicely) - .bind('keydown', '0', coverage.to_top) - .bind('keydown', '1', coverage.to_first_chunk) - ; - - $(".button_toggle_run").click(function (evt) {coverage.toggle_lines(evt.target, "run");}); - $(".button_toggle_exc").click(function (evt) {coverage.toggle_lines(evt.target, "exc");}); - $(".button_toggle_mis").click(function (evt) {coverage.toggle_lines(evt.target, "mis");}); - $(".button_toggle_par").click(function (evt) {coverage.toggle_lines(evt.target, "par");}); - - coverage.assign_shortkeys(); - coverage.wire_up_help_panel(); -}; - -coverage.toggle_lines = function (btn, cls) { - btn = $(btn); - var hide = "hide_"+cls; - if (btn.hasClass(hide)) { - $("#source ."+cls).removeClass(hide); - btn.removeClass(hide); - } - else { - $("#source ."+cls).addClass(hide); - btn.addClass(hide); - } -}; - -// Return the nth line div. -coverage.line_elt = function (n) { - return $("#t" + n); -}; - -// Return the nth line number div. -coverage.num_elt = function (n) { - return $("#n" + n); -}; - -// Return the container of all the code. -coverage.code_container = function () { - return $(".linenos"); -}; - -// Set the selection. b and e are line numbers. -coverage.set_sel = function (b, e) { - // The first line selected. - coverage.sel_begin = b; - // The next line not selected. - coverage.sel_end = (e === undefined) ? b+1 : e; -}; - -coverage.to_top = function () { - coverage.set_sel(0, 1); - coverage.scroll_window(0); -}; - -coverage.to_first_chunk = function () { - coverage.set_sel(0, 1); - coverage.to_next_chunk(); -}; - -coverage.is_transparent = function (color) { - // Different browsers return different colors for "none". - return color === "transparent" || color === "rgba(0, 0, 0, 0)"; -}; - -coverage.to_next_chunk = function () { - var c = coverage; - - // Find the start of the next colored chunk. - var probe = c.sel_end; - while (true) { - var probe_line = c.line_elt(probe); - if (probe_line.length === 0) { - return; - } - var color = probe_line.css("background-color"); - if (!c.is_transparent(color)) { - break; - } - probe++; - } - - // There's a next chunk, `probe` points to it. - var begin = probe; - - // Find the end of this chunk. - var next_color = color; - while (next_color === color) { - probe++; - probe_line = c.line_elt(probe); - next_color = probe_line.css("background-color"); - } - c.set_sel(begin, probe); - c.show_selection(); -}; - -coverage.to_prev_chunk = function () { - var c = coverage; - - // Find the end of the prev colored chunk. - var probe = c.sel_begin-1; - var probe_line = c.line_elt(probe); - if (probe_line.length === 0) { - return; - } - var color = probe_line.css("background-color"); - while (probe > 0 && c.is_transparent(color)) { - probe--; - probe_line = c.line_elt(probe); - if (probe_line.length === 0) { - return; - } - color = probe_line.css("background-color"); - } - - // There's a prev chunk, `probe` points to its last line. - var end = probe+1; - - // Find the beginning of this chunk. - var prev_color = color; - while (prev_color === color) { - probe--; - probe_line = c.line_elt(probe); - prev_color = probe_line.css("background-color"); - } - c.set_sel(probe+1, end); - c.show_selection(); -}; - -// Return the line number of the line nearest pixel position pos -coverage.line_at_pos = function (pos) { - var l1 = coverage.line_elt(1), - l2 = coverage.line_elt(2), - result; - if (l1.length && l2.length) { - var l1_top = l1.offset().top, - line_height = l2.offset().top - l1_top, - nlines = (pos - l1_top) / line_height; - if (nlines < 1) { - result = 1; - } - else { - result = Math.ceil(nlines); - } - } - else { - result = 1; - } - return result; -}; - -// Returns 0, 1, or 2: how many of the two ends of the selection are on -// the screen right now? -coverage.selection_ends_on_screen = function () { - if (coverage.sel_begin === 0) { - return 0; - } - - var top = coverage.line_elt(coverage.sel_begin); - var next = coverage.line_elt(coverage.sel_end-1); - - return ( - (top.isOnScreen() ? 1 : 0) + - (next.isOnScreen() ? 1 : 0) - ); -}; - -coverage.to_next_chunk_nicely = function () { - coverage.finish_scrolling(); - if (coverage.selection_ends_on_screen() === 0) { - // The selection is entirely off the screen: select the top line on - // the screen. - var win = $(window); - coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop())); - } - coverage.to_next_chunk(); -}; - -coverage.to_prev_chunk_nicely = function () { - coverage.finish_scrolling(); - if (coverage.selection_ends_on_screen() === 0) { - var win = $(window); - coverage.select_line_or_chunk(coverage.line_at_pos(win.scrollTop() + win.height())); - } - coverage.to_prev_chunk(); -}; - -// Select line number lineno, or if it is in a colored chunk, select the -// entire chunk -coverage.select_line_or_chunk = function (lineno) { - var c = coverage; - var probe_line = c.line_elt(lineno); - if (probe_line.length === 0) { - return; - } - var the_color = probe_line.css("background-color"); - if (!c.is_transparent(the_color)) { - // The line is in a highlighted chunk. - // Search backward for the first line. - var probe = lineno; - var color = the_color; - while (probe > 0 && color === the_color) { - probe--; - probe_line = c.line_elt(probe); - if (probe_line.length === 0) { - break; - } - color = probe_line.css("background-color"); - } - var begin = probe + 1; - - // Search forward for the last line. - probe = lineno; - color = the_color; - while (color === the_color) { - probe++; - probe_line = c.line_elt(probe); - color = probe_line.css("background-color"); - } - - coverage.set_sel(begin, probe); - } - else { - coverage.set_sel(lineno); - } -}; - -coverage.show_selection = function () { - var c = coverage; - - // Highlight the lines in the chunk - c.code_container().find(".highlight").removeClass("highlight"); - for (var probe = c.sel_begin; probe > 0 && probe < c.sel_end; probe++) { - c.num_elt(probe).addClass("highlight"); - } - - c.scroll_to_selection(); -}; - -coverage.scroll_to_selection = function () { - // Scroll the page if the chunk isn't fully visible. - if (coverage.selection_ends_on_screen() < 2) { - // Need to move the page. The html,body trick makes it scroll in all - // browsers, got it from http://stackoverflow.com/questions/3042651 - var top = coverage.line_elt(coverage.sel_begin); - var top_pos = parseInt(top.offset().top, 10); - coverage.scroll_window(top_pos - 30); - } -}; - -coverage.scroll_window = function (to_pos) { - $("html,body").animate({scrollTop: to_pos}, 200); -}; - -coverage.finish_scrolling = function () { - $("html,body").stop(true, true); -}; diff --git a/plotly/tests/coverage/index.html b/plotly/tests/coverage/index.html deleted file mode 100644 index 19a80792922..00000000000 --- a/plotly/tests/coverage/index.html +++ /dev/null @@ -1,162 +0,0 @@ - - - - - Coverage report - - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- n - s - m - x - - c   change column sorting -

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modulestatementsmissingexcludedcoverage
Total1710395077%
plotly/exceptions757091%
plotly/graph_objs/graph_objs58163089%
plotly/graph_objs/graph_objs_tools81088%
plotly/matplotlylib/mpltools21747078%
plotly/matplotlylib/renderer21759073%
plotly/plotly/plotly270104061%
plotly/tools23351078%
plotly/utils10863042%
plotly/version100100%
-
- - - - - diff --git a/plotly/tests/coverage/jquery.hotkeys.js b/plotly/tests/coverage/jquery.hotkeys.js deleted file mode 100644 index 09b21e03c7f..00000000000 --- a/plotly/tests/coverage/jquery.hotkeys.js +++ /dev/null @@ -1,99 +0,0 @@ -/* - * jQuery Hotkeys Plugin - * Copyright 2010, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * - * Based upon the plugin by Tzury Bar Yochay: - * http://github.com/tzuryby/hotkeys - * - * Original idea by: - * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/ -*/ - -(function(jQuery){ - - jQuery.hotkeys = { - version: "0.8", - - specialKeys: { - 8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause", - 20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home", - 37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del", - 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7", - 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/", - 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8", - 120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta" - }, - - shiftNums: { - "`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&", - "8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<", - ".": ">", "/": "?", "\\": "|" - } - }; - - function keyHandler( handleObj ) { - // Only care when a possible input has been specified - if ( typeof handleObj.data !== "string" ) { - return; - } - - var origHandler = handleObj.handler, - keys = handleObj.data.toLowerCase().split(" "); - - handleObj.handler = function( event ) { - // Don't fire in text-accepting inputs that we didn't directly bind to - if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) || - event.target.type === "text") ) { - return; - } - - // Keypress represents characters, not special keys - var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[ event.which ], - character = String.fromCharCode( event.which ).toLowerCase(), - key, modif = "", possible = {}; - - // check combinations (alt|ctrl|shift+anything) - if ( event.altKey && special !== "alt" ) { - modif += "alt+"; - } - - if ( event.ctrlKey && special !== "ctrl" ) { - modif += "ctrl+"; - } - - // TODO: Need to make sure this works consistently across platforms - if ( event.metaKey && !event.ctrlKey && special !== "meta" ) { - modif += "meta+"; - } - - if ( event.shiftKey && special !== "shift" ) { - modif += "shift+"; - } - - if ( special ) { - possible[ modif + special ] = true; - - } else { - possible[ modif + character ] = true; - possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true; - - // "$" can be triggered as "Shift+4" or "Shift+$" or just "$" - if ( modif === "shift+" ) { - possible[ jQuery.hotkeys.shiftNums[ character ] ] = true; - } - } - - for ( var i = 0, l = keys.length; i < l; i++ ) { - if ( possible[ keys[i] ] ) { - return origHandler.apply( this, arguments ); - } - } - }; - } - - jQuery.each([ "keydown", "keyup", "keypress" ], function() { - jQuery.event.special[ this ] = { add: keyHandler }; - }); - -})( jQuery ); diff --git a/plotly/tests/coverage/jquery.isonscreen.js b/plotly/tests/coverage/jquery.isonscreen.js deleted file mode 100644 index 0182ebd2137..00000000000 --- a/plotly/tests/coverage/jquery.isonscreen.js +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (c) 2010 - * @author Laurence Wheway - * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) - * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. - * - * @version 1.2.0 - */ -(function($) { - jQuery.extend({ - isOnScreen: function(box, container) { - //ensure numbers come in as intgers (not strings) and remove 'px' is it's there - for(var i in box){box[i] = parseFloat(box[i])}; - for(var i in container){container[i] = parseFloat(container[i])}; - - if(!container){ - container = { - left: $(window).scrollLeft(), - top: $(window).scrollTop(), - width: $(window).width(), - height: $(window).height() - } - } - - if( box.left+box.width-container.left > 0 && - box.left < container.width+container.left && - box.top+box.height-container.top > 0 && - box.top < container.height+container.top - ) return true; - return false; - } - }) - - - jQuery.fn.isOnScreen = function (container) { - for(var i in container){container[i] = parseFloat(container[i])}; - - if(!container){ - container = { - left: $(window).scrollLeft(), - top: $(window).scrollTop(), - width: $(window).width(), - height: $(window).height() - } - } - - if( $(this).offset().left+$(this).width()-container.left > 0 && - $(this).offset().left < container.width+container.left && - $(this).offset().top+$(this).height()-container.top > 0 && - $(this).offset().top < container.height+container.top - ) return true; - return false; - } -})(jQuery); diff --git a/plotly/tests/coverage/jquery.min.js b/plotly/tests/coverage/jquery.min.js deleted file mode 100644 index c941a5f7a9f..00000000000 --- a/plotly/tests/coverage/jquery.min.js +++ /dev/null @@ -1,166 +0,0 @@ -/*! - * jQuery JavaScript Library v1.4.3 - * http://jquery.com/ - * - * Copyright 2010, John Resig - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * Copyright 2010, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * - * Date: Thu Oct 14 23:10:06 2010 -0400 - */ -(function(E,A){function U(){return false}function ba(){return true}function ja(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function Ga(a){var b,d,e=[],f=[],h,k,l,n,s,v,B,D;k=c.data(this,this.nodeType?"events":"__events__");if(typeof k==="function")k=k.events;if(!(a.liveFired===this||!k||!k.live||a.button&&a.type==="click")){if(a.namespace)D=RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;var H=k.live.slice(0);for(n=0;nd)break;a.currentTarget=f.elem;a.data=f.handleObj.data; -a.handleObj=f.handleObj;D=f.handleObj.origHandler.apply(f.elem,arguments);if(D===false||a.isPropagationStopped()){d=f.level;if(D===false)b=false}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":"")+b.replace(Ha,"`").replace(Ia,"&")}function ka(a,b,d){if(c.isFunction(b))return c.grep(a,function(f,h){return!!b.call(f,h,f)===d});else if(b.nodeType)return c.grep(a,function(f){return f===b===d});else if(typeof b==="string"){var e=c.grep(a,function(f){return f.nodeType===1});if(Ja.test(b))return c.filter(b, -e,!d);else b=c.filter(b,e)}return c.grep(a,function(f){return c.inArray(f,b)>=0===d})}function la(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var e=c.data(a[d++]),f=c.data(this,e);if(e=e&&e.events){delete f.handle;f.events={};for(var h in e)for(var k in e[h])c.event.add(this,h,e[h][k],e[h][k].data)}}})}function Ka(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)} -function ma(a,b,d){var e=b==="width"?a.offsetWidth:a.offsetHeight;if(d==="border")return e;c.each(b==="width"?La:Ma,function(){d||(e-=parseFloat(c.css(a,"padding"+this))||0);if(d==="margin")e+=parseFloat(c.css(a,"margin"+this))||0;else e-=parseFloat(c.css(a,"border"+this+"Width"))||0});return e}function ca(a,b,d,e){if(c.isArray(b)&&b.length)c.each(b,function(f,h){d||Na.test(a)?e(a,h):ca(a+"["+(typeof h==="object"||c.isArray(h)?f:"")+"]",h,d,e)});else if(!d&&b!=null&&typeof b==="object")c.isEmptyObject(b)? -e(a,""):c.each(b,function(f,h){ca(a+"["+f+"]",h,d,e)});else e(a,b)}function S(a,b){var d={};c.each(na.concat.apply([],na.slice(0,b)),function(){d[this]=a});return d}function oa(a){if(!da[a]){var b=c("<"+a+">").appendTo("body"),d=b.css("display");b.remove();if(d==="none"||d==="")d="block";da[a]=d}return da[a]}function ea(a){return c.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var u=E.document,c=function(){function a(){if(!b.isReady){try{u.documentElement.doScroll("left")}catch(i){setTimeout(a, -1);return}b.ready()}}var b=function(i,r){return new b.fn.init(i,r)},d=E.jQuery,e=E.$,f,h=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,k=/\S/,l=/^\s+/,n=/\s+$/,s=/\W/,v=/\d/,B=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,D=/^[\],:{}\s]*$/,H=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,w=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,G=/(?:^|:|,)(?:\s*\[)+/g,M=/(webkit)[ \/]([\w.]+)/,g=/(opera)(?:.*version)?[ \/]([\w.]+)/,j=/(msie) ([\w.]+)/,o=/(mozilla)(?:.*? rv:([\w.]+))?/,m=navigator.userAgent,p=false, -q=[],t,x=Object.prototype.toString,C=Object.prototype.hasOwnProperty,P=Array.prototype.push,N=Array.prototype.slice,R=String.prototype.trim,Q=Array.prototype.indexOf,L={};b.fn=b.prototype={init:function(i,r){var y,z,F;if(!i)return this;if(i.nodeType){this.context=this[0]=i;this.length=1;return this}if(i==="body"&&!r&&u.body){this.context=u;this[0]=u.body;this.selector="body";this.length=1;return this}if(typeof i==="string")if((y=h.exec(i))&&(y[1]||!r))if(y[1]){F=r?r.ownerDocument||r:u;if(z=B.exec(i))if(b.isPlainObject(r)){i= -[u.createElement(z[1])];b.fn.attr.call(i,r,true)}else i=[F.createElement(z[1])];else{z=b.buildFragment([y[1]],[F]);i=(z.cacheable?z.fragment.cloneNode(true):z.fragment).childNodes}return b.merge(this,i)}else{if((z=u.getElementById(y[2]))&&z.parentNode){if(z.id!==y[2])return f.find(i);this.length=1;this[0]=z}this.context=u;this.selector=i;return this}else if(!r&&!s.test(i)){this.selector=i;this.context=u;i=u.getElementsByTagName(i);return b.merge(this,i)}else return!r||r.jquery?(r||f).find(i):b(r).find(i); -else if(b.isFunction(i))return f.ready(i);if(i.selector!==A){this.selector=i.selector;this.context=i.context}return b.makeArray(i,this)},selector:"",jquery:"1.4.3",length:0,size:function(){return this.length},toArray:function(){return N.call(this,0)},get:function(i){return i==null?this.toArray():i<0?this.slice(i)[0]:this[i]},pushStack:function(i,r,y){var z=b();b.isArray(i)?P.apply(z,i):b.merge(z,i);z.prevObject=this;z.context=this.context;if(r==="find")z.selector=this.selector+(this.selector?" ": -"")+y;else if(r)z.selector=this.selector+"."+r+"("+y+")";return z},each:function(i,r){return b.each(this,i,r)},ready:function(i){b.bindReady();if(b.isReady)i.call(u,b);else q&&q.push(i);return this},eq:function(i){return i===-1?this.slice(i):this.slice(i,+i+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(N.apply(this,arguments),"slice",N.call(arguments).join(","))},map:function(i){return this.pushStack(b.map(this,function(r,y){return i.call(r, -y,r)}))},end:function(){return this.prevObject||b(null)},push:P,sort:[].sort,splice:[].splice};b.fn.init.prototype=b.fn;b.extend=b.fn.extend=function(){var i=arguments[0]||{},r=1,y=arguments.length,z=false,F,I,K,J,fa;if(typeof i==="boolean"){z=i;i=arguments[1]||{};r=2}if(typeof i!=="object"&&!b.isFunction(i))i={};if(y===r){i=this;--r}for(;r0)){if(q){for(var r=0;i=q[r++];)i.call(u,b);q=null}b.fn.triggerHandler&&b(u).triggerHandler("ready")}}},bindReady:function(){if(!p){p=true;if(u.readyState==="complete")return setTimeout(b.ready, -1);if(u.addEventListener){u.addEventListener("DOMContentLoaded",t,false);E.addEventListener("load",b.ready,false)}else if(u.attachEvent){u.attachEvent("onreadystatechange",t);E.attachEvent("onload",b.ready);var i=false;try{i=E.frameElement==null}catch(r){}u.documentElement.doScroll&&i&&a()}}},isFunction:function(i){return b.type(i)==="function"},isArray:Array.isArray||function(i){return b.type(i)==="array"},isWindow:function(i){return i&&typeof i==="object"&&"setInterval"in i},isNaN:function(i){return i== -null||!v.test(i)||isNaN(i)},type:function(i){return i==null?String(i):L[x.call(i)]||"object"},isPlainObject:function(i){if(!i||b.type(i)!=="object"||i.nodeType||b.isWindow(i))return false;if(i.constructor&&!C.call(i,"constructor")&&!C.call(i.constructor.prototype,"isPrototypeOf"))return false;for(var r in i);return r===A||C.call(i,r)},isEmptyObject:function(i){for(var r in i)return false;return true},error:function(i){throw i;},parseJSON:function(i){if(typeof i!=="string"||!i)return null;i=b.trim(i); -if(D.test(i.replace(H,"@").replace(w,"]").replace(G,"")))return E.JSON&&E.JSON.parse?E.JSON.parse(i):(new Function("return "+i))();else b.error("Invalid JSON: "+i)},noop:function(){},globalEval:function(i){if(i&&k.test(i)){var r=u.getElementsByTagName("head")[0]||u.documentElement,y=u.createElement("script");y.type="text/javascript";if(b.support.scriptEval)y.appendChild(u.createTextNode(i));else y.text=i;r.insertBefore(y,r.firstChild);r.removeChild(y)}},nodeName:function(i,r){return i.nodeName&&i.nodeName.toUpperCase()=== -r.toUpperCase()},each:function(i,r,y){var z,F=0,I=i.length,K=I===A||b.isFunction(i);if(y)if(K)for(z in i){if(r.apply(i[z],y)===false)break}else for(;F";a=u.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var s=u.createElement("div"); -s.style.width=s.style.paddingLeft="1px";u.body.appendChild(s);c.boxModel=c.support.boxModel=s.offsetWidth===2;if("zoom"in s.style){s.style.display="inline";s.style.zoom=1;c.support.inlineBlockNeedsLayout=s.offsetWidth===2;s.style.display="";s.innerHTML="
";c.support.shrinkWrapBlocks=s.offsetWidth!==2}s.innerHTML="
t
";var v=s.getElementsByTagName("td");c.support.reliableHiddenOffsets=v[0].offsetHeight=== -0;v[0].style.display="";v[1].style.display="none";c.support.reliableHiddenOffsets=c.support.reliableHiddenOffsets&&v[0].offsetHeight===0;s.innerHTML="";u.body.removeChild(s).style.display="none"});a=function(s){var v=u.createElement("div");s="on"+s;var B=s in v;if(!B){v.setAttribute(s,"return;");B=typeof v[s]==="function"}return B};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=f=h=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength", -cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var pa={},Oa=/^(?:\{.*\}|\[.*\])$/;c.extend({cache:{},uuid:0,expando:"jQuery"+c.now(),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},data:function(a,b,d){if(c.acceptData(a)){a=a==E?pa:a;var e=a.nodeType,f=e?a[c.expando]:null,h=c.cache;if(!(e&&!f&&typeof b==="string"&&d===A)){if(e)f||(a[c.expando]=f=++c.uuid);else h=a;if(typeof b==="object")if(e)h[f]= -c.extend(h[f],b);else c.extend(h,b);else if(e&&!h[f])h[f]={};a=e?h[f]:h;if(d!==A)a[b]=d;return typeof b==="string"?a[b]:a}}},removeData:function(a,b){if(c.acceptData(a)){a=a==E?pa:a;var d=a.nodeType,e=d?a[c.expando]:a,f=c.cache,h=d?f[e]:e;if(b){if(h){delete h[b];d&&c.isEmptyObject(h)&&c.removeData(a)}}else if(d&&c.support.deleteExpando)delete a[c.expando];else if(a.removeAttribute)a.removeAttribute(c.expando);else if(d)delete f[e];else for(var k in a)delete a[k]}},acceptData:function(a){if(a.nodeName){var b= -c.noData[a.nodeName.toLowerCase()];if(b)return!(b===true||a.getAttribute("classid")!==b)}return true}});c.fn.extend({data:function(a,b){if(typeof a==="undefined")return this.length?c.data(this[0]):null;else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===A){var e=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(e===A&&this.length){e=c.data(this[0],a);if(e===A&&this[0].nodeType===1){e=this[0].getAttribute("data-"+a);if(typeof e=== -"string")try{e=e==="true"?true:e==="false"?false:e==="null"?null:!c.isNaN(e)?parseFloat(e):Oa.test(e)?c.parseJSON(e):e}catch(f){}else e=A}}return e===A&&d[1]?this.data(d[0]):e}else return this.each(function(){var h=c(this),k=[d[0],b];h.triggerHandler("setData"+d[1]+"!",k);c.data(this,a,b);h.triggerHandler("changeData"+d[1]+"!",k)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var e=c.data(a,b);if(!d)return e|| -[];if(!e||c.isArray(d))e=c.data(a,b,c.makeArray(d));else e.push(d);return e}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),e=d.shift();if(e==="inprogress")e=d.shift();if(e){b==="fx"&&d.unshift("inprogress");e.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===A)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this, -a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var qa=/[\n\t]/g,ga=/\s+/,Pa=/\r/g,Qa=/^(?:href|src|style)$/,Ra=/^(?:button|input)$/i,Sa=/^(?:button|input|object|select|textarea)$/i,Ta=/^a(?:rea)?$/i,ra=/^(?:radio|checkbox)$/i;c.fn.extend({attr:function(a,b){return c.access(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this, -a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(s){var v=c(this);v.addClass(a.call(this,s,v.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ga),d=0,e=this.length;d-1)return true;return false}, -val:function(a){if(!arguments.length){var b=this[0];if(b){if(c.nodeName(b,"option")){var d=b.attributes.value;return!d||d.specified?b.value:b.text}if(c.nodeName(b,"select")){var e=b.selectedIndex;d=[];var f=b.options;b=b.type==="select-one";if(e<0)return null;var h=b?e:0;for(e=b?e+1:f.length;h=0;else if(c.nodeName(this,"select")){var B=c.makeArray(v);c("option",this).each(function(){this.selected= -c.inArray(c(this).val(),B)>=0});if(!B.length)this.selectedIndex=-1}else this.value=v}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,e){if(!a||a.nodeType===3||a.nodeType===8)return A;if(e&&b in c.attrFn)return c(a)[b](d);e=a.nodeType!==1||!c.isXMLDoc(a);var f=d!==A;b=e&&c.props[b]||b;if(a.nodeType===1){var h=Qa.test(b);if((b in a||a[b]!==A)&&e&&!h){if(f){b==="type"&&Ra.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); -if(d===null)a.nodeType===1&&a.removeAttribute(b);else a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:Sa.test(a.nodeName)||Ta.test(a.nodeName)&&a.href?0:A;return a[b]}if(!c.support.style&&e&&b==="style"){if(f)a.style.cssText=""+d;return a.style.cssText}f&&a.setAttribute(b,""+d);if(!a.attributes[b]&&a.hasAttribute&&!a.hasAttribute(b))return A;a=!c.support.hrefNormalized&&e&& -h?a.getAttribute(b,2):a.getAttribute(b);return a===null?A:a}}});var X=/\.(.*)$/,ha=/^(?:textarea|input|select)$/i,Ha=/\./g,Ia=/ /g,Ua=/[^\w\s.|`]/g,Va=function(a){return a.replace(Ua,"\\$&")},sa={focusin:0,focusout:0};c.event={add:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(c.isWindow(a)&&a!==E&&!a.frameElement)a=E;if(d===false)d=U;var f,h;if(d.handler){f=d;d=f.handler}if(!d.guid)d.guid=c.guid++;if(h=c.data(a)){var k=a.nodeType?"events":"__events__",l=h[k],n=h.handle;if(typeof l=== -"function"){n=l.handle;l=l.events}else if(!l){a.nodeType||(h[k]=h=function(){});h.events=l={}}if(!n)h.handle=n=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(n.elem,arguments):A};n.elem=a;b=b.split(" ");for(var s=0,v;k=b[s++];){h=f?c.extend({},f):{handler:d,data:e};if(k.indexOf(".")>-1){v=k.split(".");k=v.shift();h.namespace=v.slice(0).sort().join(".")}else{v=[];h.namespace=""}h.type=k;if(!h.guid)h.guid=d.guid;var B=l[k],D=c.event.special[k]||{};if(!B){B=l[k]=[]; -if(!D.setup||D.setup.call(a,e,v,n)===false)if(a.addEventListener)a.addEventListener(k,n,false);else a.attachEvent&&a.attachEvent("on"+k,n)}if(D.add){D.add.call(a,h);if(!h.handler.guid)h.handler.guid=d.guid}B.push(h);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,e){if(!(a.nodeType===3||a.nodeType===8)){if(d===false)d=U;var f,h,k=0,l,n,s,v,B,D,H=a.nodeType?"events":"__events__",w=c.data(a),G=w&&w[H];if(w&&G){if(typeof G==="function"){w=G;G=G.events}if(b&&b.type){d=b.handler;b=b.type}if(!b|| -typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(f in G)c.event.remove(a,f+b)}else{for(b=b.split(" ");f=b[k++];){v=f;l=f.indexOf(".")<0;n=[];if(!l){n=f.split(".");f=n.shift();s=RegExp("(^|\\.)"+c.map(n.slice(0).sort(),Va).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(B=G[f])if(d){v=c.event.special[f]||{};for(h=e||0;h=0){a.type= -f=f.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[f]&&c.each(c.cache,function(){this.events&&this.events[f]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return A;a.result=A;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(e=d.nodeType?c.data(d,"handle"):(c.data(d,"__events__")||{}).handle)&&e.apply(d,b);e=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+f]&&d["on"+f].apply(d,b)=== -false){a.result=false;a.preventDefault()}}catch(h){}if(!a.isPropagationStopped()&&e)c.event.trigger(a,b,e,true);else if(!a.isDefaultPrevented()){e=a.target;var k,l=f.replace(X,""),n=c.nodeName(e,"a")&&l==="click",s=c.event.special[l]||{};if((!s._default||s._default.call(d,a)===false)&&!n&&!(e&&e.nodeName&&c.noData[e.nodeName.toLowerCase()])){try{if(e[l]){if(k=e["on"+l])e["on"+l]=null;c.event.triggered=true;e[l]()}}catch(v){}if(k)e["on"+l]=k;c.event.triggered=false}}},handle:function(a){var b,d,e; -d=[];var f,h=c.makeArray(arguments);a=h[0]=c.event.fix(a||E.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;if(!b){e=a.type.split(".");a.type=e.shift();d=e.slice(0).sort();e=RegExp("(^|\\.)"+d.join("\\.(?:.*\\.)?")+"(\\.|$)")}a.namespace=a.namespace||d.join(".");f=c.data(this,this.nodeType?"events":"__events__");if(typeof f==="function")f=f.events;d=(f||{})[a.type];if(f&&d){d=d.slice(0);f=0;for(var k=d.length;f-1?c.map(a.options,function(e){return e.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},Z=function(a,b){var d=a.target,e,f;if(!(!ha.test(d.nodeName)||d.readOnly)){e=c.data(d,"_change_data");f=va(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",f);if(!(e===A||f===e))if(e!=null||f){a.type="change";a.liveFired= -A;return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:Z,beforedeactivate:Z,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return Z.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return Z.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,"_change_data",va(a))}},setup:function(){if(this.type=== -"file")return false;for(var a in V)c.event.add(this,a+".specialChange",V[a]);return ha.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return ha.test(this.nodeName)}};V=c.event.special.change.filters;V.focus=V.beforeactivate}u.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(e){e=c.event.fix(e);e.type=b;return c.event.trigger(e,null,e.target)}c.event.special[b]={setup:function(){sa[b]++===0&&u.addEventListener(a,d,true)},teardown:function(){--sa[b]=== -0&&u.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,e,f){if(typeof d==="object"){for(var h in d)this[b](h,e,d[h],f);return this}if(c.isFunction(e)||e===false){f=e;e=A}var k=b==="one"?c.proxy(f,function(n){c(this).unbind(n,k);return f.apply(this,arguments)}):f;if(d==="unload"&&b!=="one")this.one(d,e,f);else{h=0;for(var l=this.length;h0?this.bind(b,d,e):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});E.attachEvent&&!E.addEventListener&&c(E).bind("unload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}}); -(function(){function a(g,j,o,m,p,q){p=0;for(var t=m.length;p0){C=x;break}}x=x[g]}m[p]=C}}}var d=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,e=0,f=Object.prototype.toString,h=false,k=true;[0,0].sort(function(){k=false;return 0});var l=function(g,j,o,m){o=o||[];var p=j=j||u;if(j.nodeType!==1&&j.nodeType!==9)return[];if(!g||typeof g!=="string")return o;var q=[],t,x,C,P,N=true,R=l.isXML(j),Q=g,L;do{d.exec("");if(t=d.exec(Q)){Q=t[3];q.push(t[1]);if(t[2]){P=t[3]; -break}}}while(t);if(q.length>1&&s.exec(g))if(q.length===2&&n.relative[q[0]])x=M(q[0]+q[1],j);else for(x=n.relative[q[0]]?[j]:l(q.shift(),j);q.length;){g=q.shift();if(n.relative[g])g+=q.shift();x=M(g,x)}else{if(!m&&q.length>1&&j.nodeType===9&&!R&&n.match.ID.test(q[0])&&!n.match.ID.test(q[q.length-1])){t=l.find(q.shift(),j,R);j=t.expr?l.filter(t.expr,t.set)[0]:t.set[0]}if(j){t=m?{expr:q.pop(),set:D(m)}:l.find(q.pop(),q.length===1&&(q[0]==="~"||q[0]==="+")&&j.parentNode?j.parentNode:j,R);x=t.expr?l.filter(t.expr, -t.set):t.set;if(q.length>0)C=D(x);else N=false;for(;q.length;){t=L=q.pop();if(n.relative[L])t=q.pop();else L="";if(t==null)t=j;n.relative[L](C,t,R)}}else C=[]}C||(C=x);C||l.error(L||g);if(f.call(C)==="[object Array]")if(N)if(j&&j.nodeType===1)for(g=0;C[g]!=null;g++){if(C[g]&&(C[g]===true||C[g].nodeType===1&&l.contains(j,C[g])))o.push(x[g])}else for(g=0;C[g]!=null;g++)C[g]&&C[g].nodeType===1&&o.push(x[g]);else o.push.apply(o,C);else D(C,o);if(P){l(P,p,o,m);l.uniqueSort(o)}return o};l.uniqueSort=function(g){if(w){h= -k;g.sort(w);if(h)for(var j=1;j0};l.find=function(g,j,o){var m;if(!g)return[];for(var p=0,q=n.order.length;p":function(g,j){var o=typeof j==="string",m,p=0,q=g.length;if(o&&!/\W/.test(j))for(j=j.toLowerCase();p=0))o||m.push(t);else if(o)j[q]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},CHILD:function(g){if(g[1]==="nth"){var j=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=j[1]+(j[2]||1)-0;g[3]=j[3]-0}g[0]=e++;return g},ATTR:function(g,j,o, -m,p,q){j=g[1].replace(/\\/g,"");if(!q&&n.attrMap[j])g[1]=n.attrMap[j];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,j,o,m,p){if(g[1]==="not")if((d.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=l(g[3],null,null,j);else{g=l.filter(g[3],j,o,true^p);o||m.push.apply(m,g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled=== -true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,j,o){return!!l(o[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"=== -g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},setFilters:{first:function(g,j){return j===0},last:function(g,j,o,m){return j===m.length-1},even:function(g,j){return j%2===0},odd:function(g,j){return j%2===1},lt:function(g,j,o){return jo[3]-0},nth:function(g,j,o){return o[3]- -0===j},eq:function(g,j,o){return o[3]-0===j}},filter:{PSEUDO:function(g,j,o,m){var p=j[1],q=n.filters[p];if(q)return q(g,o,j,m);else if(p==="contains")return(g.textContent||g.innerText||l.getText([g])||"").indexOf(j[3])>=0;else if(p==="not"){j=j[3];o=0;for(m=j.length;o=0}},ID:function(g,j){return g.nodeType===1&&g.getAttribute("id")===j},TAG:function(g,j){return j==="*"&&g.nodeType===1||g.nodeName.toLowerCase()=== -j},CLASS:function(g,j){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(j)>-1},ATTR:function(g,j){var o=j[1];o=n.attrHandle[o]?n.attrHandle[o](g):g[o]!=null?g[o]:g.getAttribute(o);var m=o+"",p=j[2],q=j[4];return o==null?p==="!=":p==="="?m===q:p==="*="?m.indexOf(q)>=0:p==="~="?(" "+m+" ").indexOf(q)>=0:!q?m&&o!==false:p==="!="?m!==q:p==="^="?m.indexOf(q)===0:p==="$="?m.substr(m.length-q.length)===q:p==="|="?m===q||m.substr(0,q.length+1)===q+"-":false},POS:function(g,j,o,m){var p=n.setFilters[j[2]]; -if(p)return p(g,o,j,m)}}},s=n.match.POS,v=function(g,j){return"\\"+(j-0+1)},B;for(B in n.match){n.match[B]=RegExp(n.match[B].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[B]=RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[B].source.replace(/\\(\d+)/g,v))}var D=function(g,j){g=Array.prototype.slice.call(g,0);if(j){j.push.apply(j,g);return j}return g};try{Array.prototype.slice.call(u.documentElement.childNodes,0)}catch(H){D=function(g,j){var o=j||[],m=0;if(f.call(g)==="[object Array]")Array.prototype.push.apply(o, -g);else if(typeof g.length==="number")for(var p=g.length;m";var o=u.documentElement;o.insertBefore(g,o.firstChild);if(u.getElementById(j)){n.find.ID=function(m,p,q){if(typeof p.getElementById!=="undefined"&&!q)return(p=p.getElementById(m[1]))?p.id===m[1]||typeof p.getAttributeNode!=="undefined"&&p.getAttributeNode("id").nodeValue===m[1]?[p]:A:[]};n.filter.ID=function(m,p){var q=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&q&&q.nodeValue===p}}o.removeChild(g); -o=g=null})();(function(){var g=u.createElement("div");g.appendChild(u.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(j,o){var m=o.getElementsByTagName(j[1]);if(j[1]==="*"){for(var p=[],q=0;m[q];q++)m[q].nodeType===1&&p.push(m[q]);m=p}return m};g.innerHTML="";if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(j){return j.getAttribute("href",2)};g=null})();u.querySelectorAll&& -function(){var g=l,j=u.createElement("div");j.innerHTML="

";if(!(j.querySelectorAll&&j.querySelectorAll(".TEST").length===0)){l=function(m,p,q,t){p=p||u;if(!t&&!l.isXML(p))if(p.nodeType===9)try{return D(p.querySelectorAll(m),q)}catch(x){}else if(p.nodeType===1&&p.nodeName.toLowerCase()!=="object"){var C=p.id,P=p.id="__sizzle__";try{return D(p.querySelectorAll("#"+P+" "+m),q)}catch(N){}finally{if(C)p.id=C;else p.removeAttribute("id")}}return g(m,p,q,t)};for(var o in g)l[o]=g[o]; -j=null}}();(function(){var g=u.documentElement,j=g.matchesSelector||g.mozMatchesSelector||g.webkitMatchesSelector||g.msMatchesSelector,o=false;try{j.call(u.documentElement,":sizzle")}catch(m){o=true}if(j)l.matchesSelector=function(p,q){try{if(o||!n.match.PSEUDO.test(q))return j.call(p,q)}catch(t){}return l(q,null,null,[p]).length>0}})();(function(){var g=u.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length=== -0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(j,o,m){if(typeof o.getElementsByClassName!=="undefined"&&!m)return o.getElementsByClassName(j[1])};g=null}}})();l.contains=u.documentElement.contains?function(g,j){return g!==j&&(g.contains?g.contains(j):true)}:function(g,j){return!!(g.compareDocumentPosition(j)&16)};l.isXML=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false};var M=function(g, -j){for(var o=[],m="",p,q=j.nodeType?[j]:j;p=n.match.PSEUDO.exec(g);){m+=p[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;p=0;for(var t=q.length;p0)for(var h=d;h0},closest:function(a, -b){var d=[],e,f,h=this[0];if(c.isArray(a)){var k={},l,n=1;if(h&&a.length){e=0;for(f=a.length;e-1:c(h).is(e))d.push({selector:l,elem:h,level:n})}h=h.parentNode;n++}}return d}k=$a.test(a)?c(a,b||this.context):null;e=0;for(f=this.length;e-1:c.find.matchesSelector(h,a)){d.push(h);break}else{h=h.parentNode;if(!h|| -!h.ownerDocument||h===b)break}d=d.length>1?c.unique(d):d;return this.pushStack(d,"closest",a)},index:function(a){if(!a||typeof a==="string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var d=typeof a==="string"?c(a,b||this.context):c.makeArray(a),e=c.merge(this.get(),d);return this.pushStack(!d[0]||!d[0].parentNode||d[0].parentNode.nodeType===11||!e[0]||!e[0].parentNode||e[0].parentNode.nodeType===11?e:c.unique(e))},andSelf:function(){return this.add(this.prevObject)}}); -c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling", -d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,e){var f=c.map(this,b,d);Wa.test(a)||(e=d);if(e&&typeof e==="string")f=c.filter(e,f);f=this.length>1?c.unique(f):f;if((this.length>1||Ya.test(e))&&Xa.test(a))f=f.reverse();return this.pushStack(f,a,Za.call(arguments).join(","))}}); -c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return b.length===1?c.find.matchesSelector(b[0],a)?[b[0]]:[]:c.find.matches(a,b)},dir:function(a,b,d){var e=[];for(a=a[b];a&&a.nodeType!==9&&(d===A||a.nodeType!==1||!c(a).is(d));){a.nodeType===1&&e.push(a);a=a[b]}return e},nth:function(a,b,d){b=b||1;for(var e=0;a;a=a[d])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var xa=/ jQuery\d+="(?:\d+|null)"/g, -$=/^\s+/,ya=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,za=/<([\w:]+)/,ab=/\s]+\/)>/g,O={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"], -area:[1,"",""],_default:[0,"",""]};O.optgroup=O.option;O.tbody=O.tfoot=O.colgroup=O.caption=O.thead;O.th=O.td;if(!c.support.htmlSerialize)O._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==A)return this.empty().append((this[0]&&this[0].ownerDocument||u).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this, -d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})}, -unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a= -c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,e;(e=this[d])!=null;d++)if(!a||c.filter(a,[e]).length){if(!b&&e.nodeType===1){c.cleanData(e.getElementsByTagName("*")); -c.cleanData([e])}e.parentNode&&e.parentNode.removeChild(e)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,e=this.ownerDocument;if(!d){d=e.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(xa,"").replace(cb,'="$1">').replace($, -"")],e)[0]}else return this.cloneNode(true)});if(a===true){la(this,b);la(this.find("*"),b.find("*"))}return b},html:function(a){if(a===A)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(xa,""):null;else if(typeof a==="string"&&!Aa.test(a)&&(c.support.leadingWhitespace||!$.test(a))&&!O[(za.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ya,"<$1>");try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?l.cloneNode(true):l)}k.length&&c.each(k,Ka)}return this}});c.buildFragment=function(a,b,d){var e,f,h;b=b&&b[0]?b[0].ownerDocument||b[0]:u;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===u&&!Aa.test(a[0])&&(c.support.checkClone|| -!Ba.test(a[0]))){f=true;if(h=c.fragments[a[0]])if(h!==1)e=h}if(!e){e=b.createDocumentFragment();c.clean(a,b,e,d)}if(f)c.fragments[a[0]]=h?e:1;return{fragment:e,cacheable:f}};c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var e=[];d=c(d);var f=this.length===1&&this[0].parentNode;if(f&&f.nodeType===11&&f.childNodes.length===1&&d.length===1){d[b](this[0]);return this}else{f=0;for(var h= -d.length;f0?this.clone(true):this).get();c(d[f])[b](k);e=e.concat(k)}return this.pushStack(e,a,d.selector)}}});c.extend({clean:function(a,b,d,e){b=b||u;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||u;for(var f=[],h=0,k;(k=a[h])!=null;h++){if(typeof k==="number")k+="";if(k){if(typeof k==="string"&&!bb.test(k))k=b.createTextNode(k);else if(typeof k==="string"){k=k.replace(ya,"<$1>");var l=(za.exec(k)||["",""])[1].toLowerCase(),n=O[l]||O._default, -s=n[0],v=b.createElement("div");for(v.innerHTML=n[1]+k+n[2];s--;)v=v.lastChild;if(!c.support.tbody){s=ab.test(k);l=l==="table"&&!s?v.firstChild&&v.firstChild.childNodes:n[1]===""&&!s?v.childNodes:[];for(n=l.length-1;n>=0;--n)c.nodeName(l[n],"tbody")&&!l[n].childNodes.length&&l[n].parentNode.removeChild(l[n])}!c.support.leadingWhitespace&&$.test(k)&&v.insertBefore(b.createTextNode($.exec(k)[0]),v.firstChild);k=v.childNodes}if(k.nodeType)f.push(k);else f=c.merge(f,k)}}if(d)for(h=0;f[h];h++)if(e&& -c.nodeName(f[h],"script")&&(!f[h].type||f[h].type.toLowerCase()==="text/javascript"))e.push(f[h].parentNode?f[h].parentNode.removeChild(f[h]):f[h]);else{f[h].nodeType===1&&f.splice.apply(f,[h+1,0].concat(c.makeArray(f[h].getElementsByTagName("script"))));d.appendChild(f[h])}return f},cleanData:function(a){for(var b,d,e=c.cache,f=c.event.special,h=c.support.deleteExpando,k=0,l;(l=a[k])!=null;k++)if(!(l.nodeName&&c.noData[l.nodeName.toLowerCase()]))if(d=l[c.expando]){if((b=e[d])&&b.events)for(var n in b.events)f[n]? -c.event.remove(l,n):c.removeEvent(l,n,b.handle);if(h)delete l[c.expando];else l.removeAttribute&&l.removeAttribute(c.expando);delete e[d]}}});var Ca=/alpha\([^)]*\)/i,db=/opacity=([^)]*)/,eb=/-([a-z])/ig,fb=/([A-Z])/g,Da=/^-?\d+(?:px)?$/i,gb=/^-?\d/,hb={position:"absolute",visibility:"hidden",display:"block"},La=["Left","Right"],Ma=["Top","Bottom"],W,ib=u.defaultView&&u.defaultView.getComputedStyle,jb=function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){if(arguments.length===2&&b===A)return this; -return c.access(this,a,b,true,function(d,e,f){return f!==A?c.style(d,e,f):c.css(d,e)})};c.extend({cssHooks:{opacity:{get:function(a,b){if(b){var d=W(a,"opacity","opacity");return d===""?"1":d}else return a.style.opacity}}},cssNumber:{zIndex:true,fontWeight:true,opacity:true,zoom:true,lineHeight:true},cssProps:{"float":c.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,d,e){if(!(!a||a.nodeType===3||a.nodeType===8||!a.style)){var f,h=c.camelCase(b),k=a.style,l=c.cssHooks[h];b=c.cssProps[h]|| -h;if(d!==A){if(!(typeof d==="number"&&isNaN(d)||d==null)){if(typeof d==="number"&&!c.cssNumber[h])d+="px";if(!l||!("set"in l)||(d=l.set(a,d))!==A)try{k[b]=d}catch(n){}}}else{if(l&&"get"in l&&(f=l.get(a,false,e))!==A)return f;return k[b]}}},css:function(a,b,d){var e,f=c.camelCase(b),h=c.cssHooks[f];b=c.cssProps[f]||f;if(h&&"get"in h&&(e=h.get(a,true,d))!==A)return e;else if(W)return W(a,b,f)},swap:function(a,b,d){var e={},f;for(f in b){e[f]=a.style[f];a.style[f]=b[f]}d.call(a);for(f in b)a.style[f]= -e[f]},camelCase:function(a){return a.replace(eb,jb)}});c.curCSS=c.css;c.each(["height","width"],function(a,b){c.cssHooks[b]={get:function(d,e,f){var h;if(e){if(d.offsetWidth!==0)h=ma(d,b,f);else c.swap(d,hb,function(){h=ma(d,b,f)});return h+"px"}},set:function(d,e){if(Da.test(e)){e=parseFloat(e);if(e>=0)return e+"px"}else return e}}});if(!c.support.opacity)c.cssHooks.opacity={get:function(a,b){return db.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"": -b?"1":""},set:function(a,b){var d=a.style;d.zoom=1;var e=c.isNaN(b)?"":"alpha(opacity="+b*100+")",f=d.filter||"";d.filter=Ca.test(f)?f.replace(Ca,e):d.filter+" "+e}};if(ib)W=function(a,b,d){var e;d=d.replace(fb,"-$1").toLowerCase();if(!(b=a.ownerDocument.defaultView))return A;if(b=b.getComputedStyle(a,null)){e=b.getPropertyValue(d);if(e===""&&!c.contains(a.ownerDocument.documentElement,a))e=c.style(a,d)}return e};else if(u.documentElement.currentStyle)W=function(a,b){var d,e,f=a.currentStyle&&a.currentStyle[b], -h=a.style;if(!Da.test(f)&&gb.test(f)){d=h.left;e=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;h.left=b==="fontSize"?"1em":f||0;f=h.pixelLeft+"px";h.left=d;a.runtimeStyle.left=e}return f};if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=a.offsetHeight;return a.offsetWidth===0&&b===0||!c.support.reliableHiddenOffsets&&(a.style.display||c.css(a,"display"))==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var kb=c.now(),lb=/)<[^<]*)*<\/script>/gi, -mb=/^(?:select|textarea)/i,nb=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,ob=/^(?:GET|HEAD|DELETE)$/,Na=/\[\]$/,T=/\=\?(&|$)/,ia=/\?/,pb=/([?&])_=[^&]*/,qb=/^(\w+:)?\/\/([^\/?#]+)/,rb=/%20/g,sb=/#.*$/,Ea=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!=="string"&&Ea)return Ea.apply(this,arguments);else if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var f=a.slice(e,a.length);a=a.slice(0,e)}e="GET";if(b)if(c.isFunction(b)){d= -b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);e="POST"}var h=this;c.ajax({url:a,type:e,dataType:"html",data:b,complete:function(k,l){if(l==="success"||l==="notmodified")h.html(f?c("
").append(k.responseText.replace(lb,"")).find(f):k.responseText);d&&h.each(d,[k.responseText,l,k])}});return this},serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&& -!this.disabled&&(this.checked||mb.test(this.nodeName)||nb.test(this.type))}).map(function(a,b){var d=c(this).val();return d==null?null:c.isArray(d)?c.map(d,function(e){return{name:b.name,value:e}}):{name:b.name,value:d}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:e})}, -getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,e){if(c.isFunction(b)){e=e||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:e})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return new E.XMLHttpRequest},accepts:{xml:"application/xml, text/xml",html:"text/html", -script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},ajax:function(a){var b=c.extend(true,{},c.ajaxSettings,a),d,e,f,h=b.type.toUpperCase(),k=ob.test(h);b.url=b.url.replace(sb,"");b.context=a&&a.context!=null?a.context:b;if(b.data&&b.processData&&typeof b.data!=="string")b.data=c.param(b.data,b.traditional);if(b.dataType==="jsonp"){if(h==="GET")T.test(b.url)||(b.url+=(ia.test(b.url)?"&":"?")+(b.jsonp||"callback")+"=?");else if(!b.data|| -!T.test(b.data))b.data=(b.data?b.data+"&":"")+(b.jsonp||"callback")+"=?";b.dataType="json"}if(b.dataType==="json"&&(b.data&&T.test(b.data)||T.test(b.url))){d=b.jsonpCallback||"jsonp"+kb++;if(b.data)b.data=(b.data+"").replace(T,"="+d+"$1");b.url=b.url.replace(T,"="+d+"$1");b.dataType="script";var l=E[d];E[d]=function(m){f=m;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);if(c.isFunction(l))l(m);else{E[d]=A;try{delete E[d]}catch(p){}}v&&v.removeChild(B)}}if(b.dataType==="script"&&b.cache===null)b.cache= -false;if(b.cache===false&&h==="GET"){var n=c.now(),s=b.url.replace(pb,"$1_="+n);b.url=s+(s===b.url?(ia.test(b.url)?"&":"?")+"_="+n:"")}if(b.data&&h==="GET")b.url+=(ia.test(b.url)?"&":"?")+b.data;b.global&&c.active++===0&&c.event.trigger("ajaxStart");n=(n=qb.exec(b.url))&&(n[1]&&n[1]!==location.protocol||n[2]!==location.host);if(b.dataType==="script"&&h==="GET"&&n){var v=u.getElementsByTagName("head")[0]||u.documentElement,B=u.createElement("script");if(b.scriptCharset)B.charset=b.scriptCharset;B.src= -b.url;if(!d){var D=false;B.onload=B.onreadystatechange=function(){if(!D&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){D=true;c.handleSuccess(b,w,e,f);c.handleComplete(b,w,e,f);B.onload=B.onreadystatechange=null;v&&B.parentNode&&v.removeChild(B)}}}v.insertBefore(B,v.firstChild);return A}var H=false,w=b.xhr();if(w){b.username?w.open(h,b.url,b.async,b.username,b.password):w.open(h,b.url,b.async);try{if(b.data!=null&&!k||a&&a.contentType)w.setRequestHeader("Content-Type", -b.contentType);if(b.ifModified){c.lastModified[b.url]&&w.setRequestHeader("If-Modified-Since",c.lastModified[b.url]);c.etag[b.url]&&w.setRequestHeader("If-None-Match",c.etag[b.url])}n||w.setRequestHeader("X-Requested-With","XMLHttpRequest");w.setRequestHeader("Accept",b.dataType&&b.accepts[b.dataType]?b.accepts[b.dataType]+", */*; q=0.01":b.accepts._default)}catch(G){}if(b.beforeSend&&b.beforeSend.call(b.context,w,b)===false){b.global&&c.active--===1&&c.event.trigger("ajaxStop");w.abort();return false}b.global&& -c.triggerGlobal(b,"ajaxSend",[w,b]);var M=w.onreadystatechange=function(m){if(!w||w.readyState===0||m==="abort"){H||c.handleComplete(b,w,e,f);H=true;if(w)w.onreadystatechange=c.noop}else if(!H&&w&&(w.readyState===4||m==="timeout")){H=true;w.onreadystatechange=c.noop;e=m==="timeout"?"timeout":!c.httpSuccess(w)?"error":b.ifModified&&c.httpNotModified(w,b.url)?"notmodified":"success";var p;if(e==="success")try{f=c.httpData(w,b.dataType,b)}catch(q){e="parsererror";p=q}if(e==="success"||e==="notmodified")d|| -c.handleSuccess(b,w,e,f);else c.handleError(b,w,e,p);d||c.handleComplete(b,w,e,f);m==="timeout"&&w.abort();if(b.async)w=null}};try{var g=w.abort;w.abort=function(){w&&g.call&&g.call(w);M("abort")}}catch(j){}b.async&&b.timeout>0&&setTimeout(function(){w&&!H&&M("timeout")},b.timeout);try{w.send(k||b.data==null?null:b.data)}catch(o){c.handleError(b,w,null,o);c.handleComplete(b,w,e,f)}b.async||M();return w}},param:function(a,b){var d=[],e=function(h,k){k=c.isFunction(k)?k():k;d[d.length]=encodeURIComponent(h)+ -"="+encodeURIComponent(k)};if(b===A)b=c.ajaxSettings.traditional;if(c.isArray(a)||a.jquery)c.each(a,function(){e(this.name,this.value)});else for(var f in a)ca(f,a[f],b,e);return d.join("&").replace(rb,"+")}});c.extend({active:0,lastModified:{},etag:{},handleError:function(a,b,d,e){a.error&&a.error.call(a.context,b,d,e);a.global&&c.triggerGlobal(a,"ajaxError",[b,a,e])},handleSuccess:function(a,b,d,e){a.success&&a.success.call(a.context,e,d,b);a.global&&c.triggerGlobal(a,"ajaxSuccess",[b,a])},handleComplete:function(a, -b,d){a.complete&&a.complete.call(a.context,b,d);a.global&&c.triggerGlobal(a,"ajaxComplete",[b,a]);a.global&&c.active--===1&&c.event.trigger("ajaxStop")},triggerGlobal:function(a,b,d){(a.context&&a.context.url==null?c(a.context):c.event).trigger(b,d)},httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===1223}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),e=a.getResponseHeader("Etag"); -if(d)c.lastModified[b]=d;if(e)c.etag[b]=e;return a.status===304},httpData:function(a,b,d){var e=a.getResponseHeader("content-type")||"",f=b==="xml"||!b&&e.indexOf("xml")>=0;a=f?a.responseXML:a.responseText;f&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b==="json"||!b&&e.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&e.indexOf("javascript")>=0)c.globalEval(a);return a}});if(E.ActiveXObject)c.ajaxSettings.xhr= -function(){if(E.location.protocol!=="file:")try{return new E.XMLHttpRequest}catch(a){}try{return new E.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}};c.support.ajax=!!c.ajaxSettings.xhr();var da={},tb=/^(?:toggle|show|hide)$/,ub=/^([+\-]=)?([\d+.\-]+)(.*)$/,aa,na=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b,d){if(a||a===0)return this.animate(S("show",3),a,b,d);else{a= -0;for(b=this.length;a=0;e--)if(d[e].elem===this){b&&d[e](true);d.splice(e,1)}});b||this.dequeue();return this}});c.each({slideDown:S("show",1),slideUp:S("hide",1),slideToggle:S("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,e,f){return this.animate(b, -d,e,f)}});c.extend({speed:function(a,b,d){var e=a&&typeof a==="object"?c.extend({},a):{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};e.duration=c.fx.off?0:typeof e.duration==="number"?e.duration:e.duration in c.fx.speeds?c.fx.speeds[e.duration]:c.fx.speeds._default;e.old=e.complete;e.complete=function(){e.queue!==false&&c(this).dequeue();c.isFunction(e.old)&&e.old.call(this)};return e},easing:{linear:function(a,b,d,e){return d+e*a},swing:function(a,b,d,e){return(-Math.cos(a* -Math.PI)/2+0.5)*e+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||c.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a=parseFloat(c.css(this.elem,this.prop));return a&&a>-1E4?a:0},custom:function(a,b,d){function e(h){return f.step(h)} -this.startTime=c.now();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;this.pos=this.state=0;var f=this;a=c.fx;e.elem=this.elem;if(e()&&c.timers.push(e)&&!aa)aa=setInterval(a.tick,a.interval)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true; -this.custom(this.cur(),0)},step:function(a){var b=c.now(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var e in this.options.curAnim)if(this.options.curAnim[e]!==true)d=false;if(d){if(this.options.overflow!=null&&!c.support.shrinkWrapBlocks){var f=this.elem,h=this.options;c.each(["","X","Y"],function(l,n){f.style["overflow"+n]=h.overflow[l]})}this.options.hide&&c(this.elem).hide();if(this.options.hide|| -this.options.show)for(var k in this.options.curAnim)c.style(this.elem,k,this.options.orig[k]);this.options.complete.call(this.elem)}return false}else{a=b-this.startTime;this.state=a/this.options.duration;b=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||b](this.state,a,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a= -c.timers,b=0;b-1;e={};var s={};if(n)s=f.position();k=n?s.top:parseInt(k,10)||0;l=n?s.left:parseInt(l,10)||0;if(c.isFunction(b))b=b.call(a,d,h);if(b.top!=null)e.top=b.top-h.top+k;if(b.left!=null)e.left=b.left-h.left+l;"using"in b?b.using.call(a, -e):f.css(e)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),e=Fa.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.css(a,"marginTop"))||0;d.left-=parseFloat(c.css(a,"marginLeft"))||0;e.top+=parseFloat(c.css(b[0],"borderTopWidth"))||0;e.left+=parseFloat(c.css(b[0],"borderLeftWidth"))||0;return{top:d.top-e.top,left:d.left-e.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||u.body;a&&!Fa.test(a.nodeName)&& -c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(e){var f=this[0],h;if(!f)return null;if(e!==A)return this.each(function(){if(h=ea(this))h.scrollTo(!a?e:c(h).scrollLeft(),a?e:c(h).scrollTop());else this[d]=e});else return(h=ea(f))?"pageXOffset"in h?h[a?"pageYOffset":"pageXOffset"]:c.support.boxModel&&h.document.documentElement[d]||h.document.body[d]:f[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase(); -c.fn["inner"+b]=function(){return this[0]?parseFloat(c.css(this[0],d,"padding")):null};c.fn["outer"+b]=function(e){return this[0]?parseFloat(c.css(this[0],d,e?"margin":"border")):null};c.fn[d]=function(e){var f=this[0];if(!f)return e==null?null:this;if(c.isFunction(e))return this.each(function(h){var k=c(this);k[d](e.call(this,h,k[d]()))});return c.isWindow(f)?f.document.compatMode==="CSS1Compat"&&f.document.documentElement["client"+b]||f.document.body["client"+b]:f.nodeType===9?Math.max(f.documentElement["client"+ -b],f.body["scroll"+b],f.documentElement["scroll"+b],f.body["offset"+b],f.documentElement["offset"+b]):e===A?parseFloat(c.css(f,d)):this.css(d,typeof e==="string"?e:e+"px")}})})(window); diff --git a/plotly/tests/coverage/jquery.tablesorter.min.js b/plotly/tests/coverage/jquery.tablesorter.min.js deleted file mode 100644 index 64c70071291..00000000000 --- a/plotly/tests/coverage/jquery.tablesorter.min.js +++ /dev/null @@ -1,2 +0,0 @@ - -(function($){$.extend({tablesorter:new function(){var parsers=[],widgets=[];this.defaults={cssHeader:"header",cssAsc:"headerSortUp",cssDesc:"headerSortDown",sortInitialOrder:"asc",sortMultiSortKey:"shiftKey",sortForce:null,sortAppend:null,textExtraction:"simple",parsers:{},widgets:[],widgetZebra:{css:["even","odd"]},headers:{},widthFixed:false,cancelSelection:true,sortList:[],headerList:[],dateFormat:"us",decimal:'.',debug:false};function benchmark(s,d){log(s+","+(new Date().getTime()-d.getTime())+"ms");}this.benchmark=benchmark;function log(s){if(typeof console!="undefined"&&typeof console.debug!="undefined"){console.log(s);}else{alert(s);}}function buildParserCache(table,$headers){if(table.config.debug){var parsersDebug="";}var rows=table.tBodies[0].rows;if(table.tBodies[0].rows[0]){var list=[],cells=rows[0].cells,l=cells.length;for(var i=0;i1){arr=arr.concat(checkCellColSpan(table,headerArr,row++));}else{if(table.tHead.length==1||(cell.rowSpan>1||!r[row+1])){arr.push(cell);}}}return arr;};function checkHeaderMetadata(cell){if(($.metadata)&&($(cell).metadata().sorter===false)){return true;};return false;}function checkHeaderOptions(table,i){if((table.config.headers[i])&&(table.config.headers[i].sorter===false)){return true;};return false;}function applyWidget(table){var c=table.config.widgets;var l=c.length;for(var i=0;i');$("tr:first td",table.tBodies[0]).each(function(){colgroup.append($('
').css('width',$(this).width()));});$(table).prepend(colgroup);};}function updateHeaderSortCount(table,sortList){var c=table.config,l=sortList.length;for(var i=0;ib)?1:0));};function sortTextDesc(a,b){return((ba)?1:0));};function sortNumeric(a,b){return a-b;};function sortNumericDesc(a,b){return b-a;};function getCachedSortType(parsers,i){return parsers[i].type;};this.construct=function(settings){return this.each(function(){if(!this.tHead||!this.tBodies)return;var $this,$document,$headers,cache,config,shiftDown=0,sortOrder;this.config={};config=$.extend(this.config,$.tablesorter.defaults,settings);$this=$(this);$headers=buildHeaders(this);this.config.parsers=buildParserCache(this,$headers);cache=buildCache(this);var sortCSS=[config.cssDesc,config.cssAsc];fixColumnWidth(this);$headers.click(function(e){$this.trigger("sortStart");var totalRows=($this[0].tBodies[0]&&$this[0].tBodies[0].rows.length)||0;if(!this.sortDisabled&&totalRows>0){var $cell=$(this);var i=this.column;this.order=this.count++%2;if(!e[config.sortMultiSortKey]){config.sortList=[];if(config.sortForce!=null){var a=config.sortForce;for(var j=0;j0){$this.trigger("sorton",[config.sortList]);}applyWidget(this);});};this.addParser=function(parser){var l=parsers.length,a=true;for(var i=0;i - - - - - - - Coverage for plotly/exceptions: 91% - - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
-
- - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

-

27

-

28

-

29

-

30

-

31

-

32

-

33

-

34

-

35

-

36

-

37

-

38

-

39

-

40

-

41

-

42

-

43

-

44

-

45

-

46

-

47

-

48

-

49

-

50

-

51

-

52

-

53

-

54

-

55

-

56

-

57

-

58

-

59

-

60

-

61

-

62

-

63

-

64

-

65

-

66

-

67

-

68

-

69

-

70

-

71

-

72

-

73

-

74

-

75

-

76

-

77

-

78

-

79

-

80

-

81

-

82

-

83

-

84

-

85

-

86

-

87

-

88

-

89

-

90

-

91

-

92

-

93

-

94

-

95

-

96

-

97

-

98

-

99

-

100

-

101

-

102

-

103

-

104

-

105

-

106

-

107

-

108

-

109

-

110

-

111

-

112

-

113

-

114

-

115

-

116

-

117

-

118

-

119

-

120

-

121

-

122

-

123

-

124

-

125

-

126

-

127

-

128

-

129

-

130

-

131

-

132

-

133

-

134

-

135

-

136

-

137

-

138

-

139

-

140

-

141

-

142

-

143

-

144

-

145

-

146

-

147

-

148

-

149

-

150

-

151

-

152

-

153

-

154

-

155

-

156

-

157

-

158

-

159

-

160

-

161

-

162

-

163

-

164

-

165

-

166

-

167

-

168

-

169

-

170

-

171

-

172

-

173

-

174

-

175

-

176

-

177

-

178

-

179

-

180

-

181

-

182

-

183

-

184

- -
-

""" 

-

exceptions 

-

========== 

-

 

-

A module that contains plotly's exception hierarchy. 

-

 

-

message (required!) (should be root message + caller message) 

-

info: (required!) 

-

    path_to_error (required!) 

-

    minimal_message (required!) 

-

 

-

- minimal_message is set inside this module, should not be set elsewhere 

-

 

-

- message is set inside this module, should not be set elsewhere 

-

 

-

 

-

""" 

-

 

-

 

-

## Base Plotly Error ## 

-

 

-

class PlotlyError(Exception): 

-

    pass 

-

 

-

 

-

## Graph Objects Errors ## 

-

 

-

class PlotlyGraphObjectError(PlotlyError): 

-

    def __init__(self, message='', path=None, notes=None, plain_message=''): 

-

        self.message = message 

-

        self.plain_message=plain_message 

-

        if isinstance(path, list): 

-

            self.path = path 

-

        elif path is None: 

-

            self.path = [] 

-

        else: 

-

            self.path = [path] 

-

        if isinstance(notes, list): 

-

            self.notes = notes 

-

        elif notes is None: 

-

            self.notes = [] 

-

        else: 

-

            self.notes = [notes] 

-

        super(PlotlyGraphObjectError, self).__init__(message) 

-

        self.prepare() 

-

 

-

    def add_note(self, note): 

-

        if isinstance(note, list): 

-

            self.notes += note 

-

        else: 

-

            self.notes += [note] 

-

 

-

    def add_to_error_path(self, path): 

-

        if isinstance(path, list): 

-

            self.path = path + self.path 

-

        else: 

-

            self.path = [path] + self.path 

-

 

-

    def prepare(self): 

-

        message = self.message 

-

        message += "\n\nPath To Error:\n[" 

-

        for iii, key in enumerate(self.path): 

-

            message += repr(key) 

-

            if iii < len(self.path) - 1: 

-

                message += "][" 

-

        message += "]" 

-

        if len(self.notes): 

-

            message += "\n\nAdditional Notes:\n{0}".format( 

-

                "\n".join(self.notes)) 

-

        if len(self.args) > 1: 

-

            self.args = (message, self.args[1:][0]) 

-

        else: 

-

            self.args = message, 

-

 

-

 

-

class PlotlyDictKeyError(PlotlyGraphObjectError): 

-

    def __init__(self, obj='', key='', **kwargs): 

-

        message = ( 

-

            "Invalid key, '{key}', for class, '{obj_name}'.\n\nRun " 

-

            "'help(plotly.graph_objs.{obj_name})' for more information." 

-

            "".format(key=key, obj_name=obj.__class__.__name__) 

-

        ) 

-

        plain_message = ("Invalid key, '{key}', found in '{obj}' object" 

-

                         "".format(key=key, obj=obj.__class__.__name__)) 

-

        super(PlotlyDictKeyError, self).__init__(message=message, 

-

                                                 path=[key], 

-

                                                 plain_message=plain_message, 

-

                                                 **kwargs) 

-

 

-

 

-

class PlotlyDictValueError(PlotlyGraphObjectError): 

-

    def __init__(self, obj='', key='', value='', val_types='', **kwargs): 

-

        message = ( 

-

            "Invalid value type, '{value_name}', associated with key, " 

-

            "'{key}', for class, '{obj_name}'.\nValid types for this key " 

-

            "are:\n '{val_types}'.\n\nRun 'help(plotly.graph_objs.{obj_name})' " 

-

            "for more information.".format(key=key, 

-

                                           value_name=value.__class__.__name__, 

-

                                           val_types=val_types, 

-

                                           obj_name=obj.__class__.__name__) 

-

        ) 

-

        plain_message = ("Invalid value found in '{obj}' associated with key, " 

-

                         "'{key}'".format(key=key, obj=obj.__class__.__name__)) 

-

        super(PlotlyDictValueError, self).__init__(message=message, 

-

                                                   plain_message=plain_message, 

-

                                                   path=[key], 

-

                                                   **kwargs) 

-

 

-

 

-

class PlotlyListEntryError(PlotlyGraphObjectError): 

-

    def __init__(self, obj='', index='', entry='', **kwargs): 

-

        message = ( 

-

            "The entry at index, '{0}', is invalid in a '{1}' object" 

-

            "".format(index, obj.__class__.__name__) 

-

        ) 

-

        plain_message = ( 

-

            "Invalid entry found in '{obj}' object at index, '{index}'." 

-

            "".format(obj=obj.__class__.__name__, index=index) 

-

        ) 

-

        super(PlotlyListEntryError, self).__init__(message=message, 

-

                                                   plain_message=plain_message, 

-

                                                   path=[index], 

-

                                                   **kwargs) 

-

 

-

 

-

class PlotlyDataTypeError(PlotlyGraphObjectError): 

-

    def __init__(self, obj='', index='', **kwargs): 

-

        message = ( 

-

                "The entry at index, '{0}', is invalid because it does not " 

-

                "contain a valid 'type' key-value. This is required for valid " 

-

                "'{1}' lists.".format(index, obj.__class__.__name__) 

-

        ) 

-

        plain_message = ( 

-

                "Invalid entry found in 'data' object at index, '{0}'. It " 

-

                "does not contain a valid 'type' key, required for 'data' " 

-

                "lists.".format(index)) 

-

        super(PlotlyDataTypeError, self).__init__(message=message, 

-

                                                  plain_message=plain_message, 

-

                                                  path=[index], 

-

                                                  **kwargs) 

-

 

-

 

-

## Local Config Errors ## 

-

 

-

class PlotlyLocalError(PlotlyError): 

-

    pass 

-

 

-

 

-

class PlotlyLocalCredentialsError(PlotlyLocalError): 

-

    def __init__(self): 

-

        message = ("\n" 

-

            "Couldn't find a 'username', 'api-key' pair for you on your local " 

-

            "machine. To sign in temporarily (until you stop running Python), " 

-

            "run:\n" 

-

            ">>> import plotly.plotly as py\n" 

-

            ">>> py.sign_in('username', 'api_key')\n\n" 

-

            "Even better, save your credentials permanently using the 'tools' " 

-

            "module:\n" 

-

            ">>> import plotly.tools as tls\n" 

-

            ">>> tls.set_credentials_file(username='username', api_key='api-key')\n\n" 

-

            "For more help, see https://plot.ly/python.\n") 

-

        super(PlotlyLocalCredentialsError, self).__init__(message) 

-

 

-

 

-

## Server Errors ## 

-

 

-

class PlotlyServerError(PlotlyError): 

-

    pass 

-

 

-

 

-

class PlotlyConnectionError(PlotlyServerError): 

-

    pass 

-

 

-

 

-

class PlotlyCredentialError(PlotlyServerError): 

-

    pass 

-

 

-

 

-

class PlotlyAccountError(PlotlyServerError): 

-

    pass 

-

 

-

 

-

class PlotlyRateLimitError(PlotlyServerError): 

-

    pass 

- -
- - - - - - diff --git a/plotly/tests/coverage/plotly_graph_objs_graph_objs.html b/plotly/tests/coverage/plotly_graph_objs_graph_objs.html deleted file mode 100644 index 8f73eeae679..00000000000 --- a/plotly/tests/coverage/plotly_graph_objs_graph_objs.html +++ /dev/null @@ -1,3112 +0,0 @@ - - - - - - - - Coverage for plotly/graph_objs/graph_objs: 89% - - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

-

27

-

28

-

29

-

30

-

31

-

32

-

33

-

34

-

35

-

36

-

37

-

38

-

39

-

40

-

41

-

42

-

43

-

44

-

45

-

46

-

47

-

48

-

49

-

50

-

51

-

52

-

53

-

54

-

55

-

56

-

57

-

58

-

59

-

60

-

61

-

62

-

63

-

64

-

65

-

66

-

67

-

68

-

69

-

70

-

71

-

72

-

73

-

74

-

75

-

76

-

77

-

78

-

79

-

80

-

81

-

82

-

83

-

84

-

85

-

86

-

87

-

88

-

89

-

90

-

91

-

92

-

93

-

94

-

95

-

96

-

97

-

98

-

99

-

100

-

101

-

102

-

103

-

104

-

105

-

106

-

107

-

108

-

109

-

110

-

111

-

112

-

113

-

114

-

115

-

116

-

117

-

118

-

119

-

120

-

121

-

122

-

123

-

124

-

125

-

126

-

127

-

128

-

129

-

130

-

131

-

132

-

133

-

134

-

135

-

136

-

137

-

138

-

139

-

140

-

141

-

142

-

143

-

144

-

145

-

146

-

147

-

148

-

149

-

150

-

151

-

152

-

153

-

154

-

155

-

156

-

157

-

158

-

159

-

160

-

161

-

162

-

163

-

164

-

165

-

166

-

167

-

168

-

169

-

170

-

171

-

172

-

173

-

174

-

175

-

176

-

177

-

178

-

179

-

180

-

181

-

182

-

183

-

184

-

185

-

186

-

187

-

188

-

189

-

190

-

191

-

192

-

193

-

194

-

195

-

196

-

197

-

198

-

199

-

200

-

201

-

202

-

203

-

204

-

205

-

206

-

207

-

208

-

209

-

210

-

211

-

212

-

213

-

214

-

215

-

216

-

217

-

218

-

219

-

220

-

221

-

222

-

223

-

224

-

225

-

226

-

227

-

228

-

229

-

230

-

231

-

232

-

233

-

234

-

235

-

236

-

237

-

238

-

239

-

240

-

241

-

242

-

243

-

244

-

245

-

246

-

247

-

248

-

249

-

250

-

251

-

252

-

253

-

254

-

255

-

256

-

257

-

258

-

259

-

260

-

261

-

262

-

263

-

264

-

265

-

266

-

267

-

268

-

269

-

270

-

271

-

272

-

273

-

274

-

275

-

276

-

277

-

278

-

279

-

280

-

281

-

282

-

283

-

284

-

285

-

286

-

287

-

288

-

289

-

290

-

291

-

292

-

293

-

294

-

295

-

296

-

297

-

298

-

299

-

300

-

301

-

302

-

303

-

304

-

305

-

306

-

307

-

308

-

309

-

310

-

311

-

312

-

313

-

314

-

315

-

316

-

317

-

318

-

319

-

320

-

321

-

322

-

323

-

324

-

325

-

326

-

327

-

328

-

329

-

330

-

331

-

332

-

333

-

334

-

335

-

336

-

337

-

338

-

339

-

340

-

341

-

342

-

343

-

344

-

345

-

346

-

347

-

348

-

349

-

350

-

351

-

352

-

353

-

354

-

355

-

356

-

357

-

358

-

359

-

360

-

361

-

362

-

363

-

364

-

365

-

366

-

367

-

368

-

369

-

370

-

371

-

372

-

373

-

374

-

375

-

376

-

377

-

378

-

379

-

380

-

381

-

382

-

383

-

384

-

385

-

386

-

387

-

388

-

389

-

390

-

391

-

392

-

393

-

394

-

395

-

396

-

397

-

398

-

399

-

400

-

401

-

402

-

403

-

404

-

405

-

406

-

407

-

408

-

409

-

410

-

411

-

412

-

413

-

414

-

415

-

416

-

417

-

418

-

419

-

420

-

421

-

422

-

423

-

424

-

425

-

426

-

427

-

428

-

429

-

430

-

431

-

432

-

433

-

434

-

435

-

436

-

437

-

438

-

439

-

440

-

441

-

442

-

443

-

444

-

445

-

446

-

447

-

448

-

449

-

450

-

451

-

452

-

453

-

454

-

455

-

456

-

457

-

458

-

459

-

460

-

461

-

462

-

463

-

464

-

465

-

466

-

467

-

468

-

469

-

470

-

471

-

472

-

473

-

474

-

475

-

476

-

477

-

478

-

479

-

480

-

481

-

482

-

483

-

484

-

485

-

486

-

487

-

488

-

489

-

490

-

491

-

492

-

493

-

494

-

495

-

496

-

497

-

498

-

499

-

500

-

501

-

502

-

503

-

504

-

505

-

506

-

507

-

508

-

509

-

510

-

511

-

512

-

513

-

514

-

515

-

516

-

517

-

518

-

519

-

520

-

521

-

522

-

523

-

524

-

525

-

526

-

527

-

528

-

529

-

530

-

531

-

532

-

533

-

534

-

535

-

536

-

537

-

538

-

539

-

540

-

541

-

542

-

543

-

544

-

545

-

546

-

547

-

548

-

549

-

550

-

551

-

552

-

553

-

554

-

555

-

556

-

557

-

558

-

559

-

560

-

561

-

562

-

563

-

564

-

565

-

566

-

567

-

568

-

569

-

570

-

571

-

572

-

573

-

574

-

575

-

576

-

577

-

578

-

579

-

580

-

581

-

582

-

583

-

584

-

585

-

586

-

587

-

588

-

589

-

590

-

591

-

592

-

593

-

594

-

595

-

596

-

597

-

598

-

599

-

600

-

601

-

602

-

603

-

604

-

605

-

606

-

607

-

608

-

609

-

610

-

611

-

612

-

613

-

614

-

615

-

616

-

617

-

618

-

619

-

620

-

621

-

622

-

623

-

624

-

625

-

626

-

627

-

628

-

629

-

630

-

631

-

632

-

633

-

634

-

635

-

636

-

637

-

638

-

639

-

640

-

641

-

642

-

643

-

644

-

645

-

646

-

647

-

648

-

649

-

650

-

651

-

652

-

653

-

654

-

655

-

656

-

657

-

658

-

659

-

660

-

661

-

662

-

663

-

664

-

665

-

666

-

667

-

668

-

669

-

670

-

671

-

672

-

673

-

674

-

675

-

676

-

677

-

678

-

679

-

680

-

681

-

682

-

683

-

684

-

685

-

686

-

687

-

688

-

689

-

690

-

691

-

692

-

693

-

694

-

695

-

696

-

697

-

698

-

699

-

700

-

701

-

702

-

703

-

704

-

705

-

706

-

707

-

708

-

709

-

710

-

711

-

712

-

713

-

714

-

715

-

716

-

717

-

718

-

719

-

720

-

721

-

722

-

723

-

724

-

725

-

726

-

727

-

728

-

729

-

730

-

731

-

732

-

733

-

734

-

735

-

736

-

737

-

738

-

739

-

740

-

741

-

742

-

743

-

744

-

745

-

746

-

747

-

748

-

749

-

750

-

751

-

752

-

753

-

754

-

755

-

756

-

757

-

758

-

759

-

760

-

761

-

762

-

763

-

764

-

765

-

766

-

767

-

768

-

769

-

770

-

771

-

772

-

773

-

774

-

775

-

776

-

777

-

778

-

779

-

780

-

781

-

782

-

783

-

784

-

785

-

786

-

787

-

788

-

789

-

790

-

791

-

792

-

793

-

794

-

795

-

796

-

797

-

798

-

799

-

800

-

801

-

802

-

803

-

804

-

805

-

806

-

807

-

808

-

809

-

810

-

811

-

812

-

813

-

814

-

815

-

816

-

817

-

818

-

819

-

820

-

821

-

822

-

823

-

824

-

825

-

826

-

827

-

828

-

829

-

830

-

831

-

832

-

833

-

834

-

835

-

836

-

837

-

838

-

839

-

840

-

841

-

842

-

843

-

844

-

845

-

846

-

847

-

848

-

849

-

850

-

851

-

852

-

853

-

854

-

855

-

856

-

857

-

858

-

859

-

860

-

861

-

862

-

863

-

864

-

865

-

866

-

867

-

868

-

869

-

870

-

871

-

872

-

873

-

874

-

875

-

876

-

877

-

878

-

879

-

880

-

881

-

882

-

883

-

884

-

885

-

886

-

887

-

888

-

889

-

890

-

891

-

892

-

893

-

894

-

895

-

896

-

897

-

898

-

899

-

900

-

901

-

902

-

903

-

904

-

905

-

906

-

907

-

908

-

909

-

910

-

911

-

912

-

913

-

914

-

915

-

916

-

917

-

918

-

919

-

920

-

921

-

922

-

923

-

924

-

925

-

926

-

927

-

928

-

929

-

930

-

931

-

932

-

933

-

934

-

935

-

936

-

937

-

938

-

939

-

940

-

941

-

942

-

943

-

944

-

945

-

946

-

947

-

948

-

949

-

950

-

951

-

952

-

953

-

954

-

955

-

956

-

957

-

958

-

959

-

960

-

961

-

962

-

963

-

964

-

965

-

966

-

967

-

968

-

969

-

970

-

971

-

972

-

973

-

974

-

975

-

976

-

977

-

978

-

979

-

980

-

981

-

982

-

983

-

984

-

985

-

986

-

987

-

988

-

989

-

990

-

991

-

992

-

993

-

994

-

995

-

996

-

997

-

998

-

999

-

1000

-

1001

-

1002

-

1003

-

1004

-

1005

-

1006

-

1007

-

1008

-

1009

-

1010

-

1011

-

1012

-

1013

-

1014

-

1015

-

1016

-

1017

-

1018

-

1019

-

1020

-

1021

-

1022

-

1023

-

1024

-

1025

-

1026

-

1027

-

1028

-

1029

-

1030

-

1031

-

1032

-

1033

-

1034

-

1035

-

1036

-

1037

-

1038

-

1039

-

1040

-

1041

-

1042

-

1043

-

1044

-

1045

-

1046

-

1047

-

1048

-

1049

-

1050

-

1051

-

1052

-

1053

-

1054

-

1055

-

1056

-

1057

-

1058

-

1059

-

1060

-

1061

-

1062

-

1063

-

1064

-

1065

-

1066

-

1067

-

1068

-

1069

-

1070

-

1071

-

1072

-

1073

-

1074

-

1075

-

1076

-

1077

-

1078

-

1079

-

1080

-

1081

-

1082

-

1083

-

1084

-

1085

-

1086

-

1087

-

1088

-

1089

-

1090

-

1091

-

1092

-

1093

-

1094

-

1095

-

1096

-

1097

-

1098

-

1099

-

1100

-

1101

-

1102

-

1103

-

1104

-

1105

-

1106

-

1107

-

1108

-

1109

-

1110

-

1111

-

1112

-

1113

-

1114

-

1115

-

1116

-

1117

-

1118

-

1119

-

1120

-

1121

-

1122

-

1123

-

1124

-

1125

-

1126

-

1127

-

1128

-

1129

-

1130

-

1131

-

1132

-

1133

-

1134

-

1135

-

1136

-

1137

-

1138

-

1139

-

1140

-

1141

-

1142

-

1143

-

1144

-

1145

-

1146

-

1147

-

1148

-

1149

-

1150

-

1151

-

1152

-

1153

-

1154

-

1155

-

1156

-

1157

-

1158

-

1159

-

1160

-

1161

-

1162

-

1163

-

1164

-

1165

-

1166

-

1167

-

1168

-

1169

-

1170

-

1171

-

1172

-

1173

-

1174

-

1175

-

1176

-

1177

-

1178

-

1179

-

1180

-

1181

-

1182

-

1183

-

1184

-

1185

-

1186

-

1187

-

1188

-

1189

-

1190

-

1191

-

1192

-

1193

-

1194

-

1195

-

1196

-

1197

-

1198

-

1199

-

1200

-

1201

-

1202

-

1203

-

1204

-

1205

-

1206

-

1207

-

1208

-

1209

-

1210

-

1211

-

1212

-

1213

-

1214

-

1215

-

1216

-

1217

-

1218

-

1219

-

1220

-

1221

-

1222

-

1223

-

1224

-

1225

-

1226

-

1227

-

1228

-

1229

-

1230

-

1231

-

1232

-

1233

-

1234

-

1235

-

1236

-

1237

-

1238

-

1239

-

1240

-

1241

-

1242

-

1243

-

1244

-

1245

-

1246

-

1247

-

1248

-

1249

-

1250

-

1251

-

1252

-

1253

-

1254

-

1255

-

1256

-

1257

-

1258

-

1259

-

1260

-

1261

-

1262

-

1263

-

1264

-

1265

-

1266

-

1267

-

1268

-

1269

-

1270

-

1271

-

1272

-

1273

-

1274

-

1275

-

1276

-

1277

-

1278

-

1279

-

1280

-

1281

-

1282

-

1283

-

1284

-

1285

-

1286

-

1287

-

1288

-

1289

-

1290

-

1291

-

1292

-

1293

-

1294

-

1295

-

1296

-

1297

-

1298

-

1299

-

1300

-

1301

-

1302

-

1303

-

1304

-

1305

-

1306

-

1307

-

1308

-

1309

-

1310

-

1311

-

1312

-

1313

-

1314

-

1315

-

1316

-

1317

-

1318

-

1319

-

1320

-

1321

-

1322

-

1323

-

1324

-

1325

-

1326

-

1327

-

1328

-

1329

-

1330

-

1331

-

1332

-

1333

-

1334

-

1335

-

1336

-

1337

-

1338

-

1339

-

1340

-

1341

-

1342

-

1343

-

1344

-

1345

-

1346

-

1347

-

1348

-

1349

-

1350

-

1351

-

1352

-

1353

-

1354

-

1355

-

1356

-

1357

-

1358

-

1359

-

1360

-

1361

-

1362

-

1363

-

1364

-

1365

-

1366

-

1367

-

1368

-

1369

-

1370

-

1371

-

1372

-

1373

-

1374

-

1375

-

1376

-

1377

-

1378

-

1379

-

1380

-

1381

-

1382

-

1383

-

1384

-

1385

-

1386

-

1387

-

1388

-

1389

-

1390

-

1391

-

1392

-

1393

-

1394

-

1395

-

1396

-

1397

-

1398

-

1399

-

1400

-

1401

-

1402

-

1403

-

1404

-

1405

-

1406

-

1407

-

1408

-

1409

-

1410

-

1411

-

1412

-

1413

-

1414

-

1415

-

1416

-

1417

-

1418

-

1419

-

1420

-

1421

-

1422

-

1423

-

1424

-

1425

-

1426

-

1427

-

1428

-

1429

-

1430

-

1431

-

1432

-

1433

-

1434

-

1435

-

1436

-

1437

-

1438

-

1439

-

1440

-

1441

-

1442

-

1443

-

1444

-

1445

-

1446

-

1447

-

1448

-

1449

-

1450

-

1451

-

1452

-

1453

-

1454

-

1455

-

1456

-

1457

-

1458

-

1459

-

1460

-

1461

-

1462

-

1463

-

1464

-

1465

-

1466

-

1467

-

1468

-

1469

-

1470

-

1471

-

1472

-

1473

-

1474

-

1475

-

1476

-

1477

-

1478

-

1479

-

1480

-

1481

-

1482

-

1483

-

1484

-

1485

-

1486

-

1487

-

1488

-

1489

-

1490

-

1491

-

1492

-

1493

-

1494

-

1495

-

1496

-

1497

-

1498

-

1499

-

1500

-

1501

-

1502

-

1503

-

1504

-

1505

-

1506

-

1507

-

1508

-

1509

-

1510

-

1511

-

1512

-

1513

-

1514

-

1515

- -
-

""" 

-

graph_objs 

-

========== 

-

 

-

A module that understands plotly language and can manage the json 

-

structures. This module defines two base classes: PlotlyList and PlotlyDict. 

-

The former inherits from `list` and the latter inherits from `dict`. and is 

-

A third structure, PlotlyTrace, is also considered a base class for all 

-

subclassing 'trace' objects like Scatter, Box, Bar, etc. It is also not meant 

-

to instantiated by users. 

-

 

-

Goals of this module: 

-

--------------------- 

-

 

-

* A dict/list with the same entries as a PlotlyDict/PlotlyList should look 

-

exactly the same once a call is made to plot. 

-

 

-

* Only mutate object structure when users ASK for it. 

-

 

-

* It should always be possible to get a dict/list JSON representation from a 

-

graph_objs object and it should always be possible to make a graph_objs object 

-

from a dict/list JSON representation. 

-

 

-

""" 

-

from __future__ import absolute_import 

-

 

-

import warnings 

-

import textwrap 

-

import six 

-

import sys 

-

from plotly.graph_objs import graph_objs_tools 

-

import copy 

-

from plotly import exceptions 

-

from plotly import utils 

-

 

-

if sys.version[:3] == '2.6': 

-

    from ordereddict import OrderedDict 

-

    import simplejson as json 

-

else: 

-

    from collections import OrderedDict 

-

    import json 

-

 

-

__all__ = ["Data", 

-

           "Annotations", 

-

           "Area", 

-

           "Bar", 

-

           "Box", 

-

           "Contour", 

-

           "Heatmap", 

-

           "Histogram", 

-

           "Histogram2d", 

-

           "Histogram2dContour", 

-

           "Scatter", 

-

           "Annotation", 

-

           "AngularAxis", 

-

           "ColorBar", 

-

           "Contours", 

-

           "ErrorX", 

-

           "ErrorY", 

-

           "Figure", 

-

           "Font", 

-

           "Layout", 

-

           "Legend", 

-

           "Line", 

-

           "Margin", 

-

           "Marker", 

-

           "RadialAxis", 

-

           "Stream", 

-

           "Trace", 

-

           "XAxis", 

-

           "XBins", 

-

           "YAxis", 

-

           "YBins"] 

-

 

-

# TODO: BIG ONE, how should exceptions bubble up in this inheritance scheme? 

-

    # TODO: related, WHAT exceptions should bubble up? 

-

 

-

from pkg_resources import resource_string 

-

s = resource_string('plotly', 

-

                    'graph_reference/graph_objs_meta.json').decode('utf-8') 

-

INFO = json.loads(s, object_pairs_hook=OrderedDict) 

-

 

-

INFO = utils.decode_unicode(INFO) 

-

 

-

# define how to map from keys in INFO to a class 

-

# mapping: (n->m, m < n) 

-

KEY_TO_NAME = dict( 

-

    plotlylist='PlotlyList', 

-

    data='Data', 

-

    angularaxis='AngularAxis', 

-

    annotations='Annotations', 

-

    area='Area', 

-

    plotlydict='PlotlyDict', 

-

    plotlytrace='PlotlyTrace', 

-

    bar='Bar', 

-

    box='Box', 

-

    contour='Contour', 

-

    heatmap='Heatmap', 

-

    histogram='Histogram', 

-

    histogram2d='Histogram2d', 

-

    histogram2dcontour='Histogram2dContour', 

-

    scatter='Scatter', 

-

    annotation='Annotation', 

-

    colorbar='ColorBar', 

-

    contours='Contours', 

-

    error_x='ErrorX', 

-

    error_y='ErrorY', 

-

    figure='Figure', 

-

    font='Font', 

-

    layout='Layout', 

-

    legend='Legend', 

-

    line='Line', 

-

    margin='Margin', 

-

    marker='Marker', 

-

    radialaxis='RadialAxis', 

-

    stream='Stream', 

-

    trace='Trace', 

-

    textfont='Font', 

-

    tickfont='Font', 

-

    titlefont='Font', 

-

    xaxis='XAxis', 

-

    xbins='XBins', 

-

    yaxis='YAxis', 

-

    ybins='YBins' 

-

) 

-

 

-

# define how to map from a class name to a key name in INFO 

-

# mapping: (n->n) 

-

NAME_TO_KEY = dict( 

-

    PlotlyList='plotlylist', 

-

    Data='data', 

-

    AngularAxis='angularaxis', 

-

    Annotations='annotations', 

-

    PlotlyDict='plotlydict', 

-

    PlotlyTrace='plotlytrace', 

-

    Area='area', 

-

    Bar='bar', 

-

    Box='box', 

-

    Contour='contour', 

-

    Heatmap='heatmap', 

-

    Histogram='histogram', 

-

    Histogram2d='histogram2d', 

-

    Histogram2dContour='histogram2dcontour', 

-

    Scatter='scatter', 

-

    Annotation='annotation', 

-

    ColorBar='colorbar', 

-

    Contours='contours', 

-

    ErrorX='error_x', 

-

    ErrorY='error_y', 

-

    Figure='figure', 

-

    Font='font', 

-

    Layout='layout', 

-

    Legend='legend', 

-

    Line='line', 

-

    Margin='margin', 

-

    Marker='marker', 

-

    RadialAxis='radialaxis', 

-

    Stream='stream', 

-

    Trace='trace', 

-

    XAxis='xaxis', 

-

    XBins='xbins', 

-

    YAxis='yaxis', 

-

    YBins='ybins' 

-

) 

-

 

-

 

-

class ListMeta(type): 

-

    """A meta class for PlotlyList class creation. 

-

 

-

    The sole purpose of this meta class is to properly create the __doc__ 

-

    attribute so that running help(Obj), where Obj is a subclass of PlotlyList, 

-

    will return useful information for that object. 

-

 

-

    """ 

-

 

-

    def __new__(mcs, name, bases, attrs): 

-

        doc = attrs['__doc__'] 

-

        tab_size = 4 

-

        min_indent = min([len(a) - len(b) 

-

                          for a, b in zip(doc.splitlines(), 

-

                                          [l.lstrip() 

-

                                           for l in doc.splitlines()])]) 

-

        doc = "".join([line[min_indent:] + '\n' for line in doc.splitlines()]) 

-

        # Add section header for method list... 

-

        doc += "Quick method reference:\n\n" 

-

        doc += "\t{0}.".format(name) + "\n\t{0}.".format(name).join( 

-

            ["update(changes)", "strip_style()", "get_data()", 

-

             "to_graph_objs()", "validate()", "to_string()", 

-

             "force_clean()"]) + "\n\n" 

-

        attrs['__doc__'] = doc.expandtabs(tab_size) 

-

        return super(ListMeta, mcs).__new__(mcs, name, bases, attrs) 

-

 

-

 

-

class DictMeta(type): 

-

    """A meta class for PlotlyDict class creation. 

-

 

-

    The sole purpose of this meta class is to properly create the __doc__ 

-

    attribute so that running help(Obj), where Obj is a subclass of PlotlyDict, 

-

    will return information about key-value pairs for that object. 

-

 

-

    """ 

-

    def __new__(mcs, name, bases, attrs): 

-

        obj_key = NAME_TO_KEY[name] 

-

        # remove min indentation... 

-

        doc = attrs['__doc__'] 

-

        obj_info = INFO[obj_key] 

-

        line_size = 76 

-

        tab_size = 4 

-

        min_indent = min([len(a) - len(b) 

-

                          for a, b in zip(doc.splitlines(), 

-

                                          [l.lstrip() 

-

                                           for l in doc.splitlines()])]) 

-

        doc = "".join([line[min_indent:] + '\n' for line in doc.splitlines()]) 

-

        # Add section header for method list... 

-

        doc += "Quick method reference:\n\n" 

-

        doc += "\t{0}.".format(name) + "\n\t{0}.".format(name).join( 

-

            ["update(changes)", "strip_style()", "get_data()", 

-

             "to_graph_objs()", "validate()", "to_string()", 

-

             "force_clean()"]) + "\n\n" 

-

        # Add section header 

-

        if len(obj_info): 

-

            doc += "Valid keys:\n\n" 

-

            # Add each key one-by-one and format 

-

            width1 = line_size-tab_size 

-

            width2 = line_size-2*tab_size 

-

            width3 = line_size-3*tab_size 

-

            undocumented = "Aw, snap! Undocumented!" 

-

            for key in obj_info: 

-

                # main portion of documentation 

-

                try: 

-

                    required = str(obj_info[key]['required']) 

-

                except KeyError: 

-

                    required = undocumented 

-

 

-

                try: 

-

                    typ = str(obj_info[key]['type']) 

-

                except KeyError: 

-

                    typ = undocumented 

-

 

-

                try: 

-

                    val_types = str(obj_info[key]['val_types']) 

-

                    if typ == 'object': 

-

                        val_types = "{0} object | ".format(KEY_TO_NAME[key])+\ 

-

                                    val_types 

-

                except KeyError: 

-

                    val_types = undocumented 

-

                try: 

-

                    descr = str(obj_info[key]['description']) 

-

                except KeyError: 

-

                    descr = undocumented 

-

                str_1 = "{0} [required={1}] (value={2})".format( 

-

                    key, required, val_types) 

-

                if "streamable" in obj_info[key] and obj_info[key]["streamable"]: 

-

                    str_1 += " (streamable)" 

-

                str_1 += ":\n" 

-

                str_1 = "\t" + "\n\t".join(textwrap.wrap(str_1, 

-

                                                         width=width1)) + "\n" 

-

                str_2 = "\t\t" + "\n\t\t".join(textwrap.wrap(descr, 

-

                                               width=width2)) + "\n" 

-

                doc += str_1 + str_2 

-

                # if a user can run help on this value, tell them! 

-

                if typ == "object": 

-

                    doc += "\n\t\tFor more, run `help(plotly.graph_objs.{0" \ 

-

                           "})`\n".format(KEY_TO_NAME[key]) 

-

                # if example usage exists, tell them! 

-

                if 'examples' in obj_info[key]: 

-

                    ex = "\n\t\tExamples:\n" + "\t\t\t" 

-

                    ex += "\n\t\t\t".join( 

-

                        textwrap.wrap(str(obj_info[key]['examples']), 

-

                                      width=width3)) + "\n" 

-

                    doc += ex 

-

                if 'code' in obj_info[key]: 

-

                    code = "\n\t\tCode snippet:" 

-

                    code += "\n\t\t\t>>>".join( 

-

                        str(obj_info[key]['code']).split('>>>')) + "\n" 

-

                    doc += code 

-

                doc += '\n' 

-

        attrs['__doc__'] = doc.expandtabs(tab_size) 

-

        return super(DictMeta, mcs).__new__(mcs, name, bases, attrs) 

-

 

-

@six.add_metaclass(ListMeta) 

-

class PlotlyList(list): 

-

    """A container for PlotlyDicts, inherits from standard list. 

-

 

-

    Plotly uses lists and dicts as collections to hold information about a 

-

    figure. This container is simply a list that understands some plotly 

-

    language and apes the methods in a PlotlyDict, passing them on to its 

-

    constituents. 

-

 

-

    It can be initialized like any other list so long as the entries are all 

-

    PlotlyDict objects or subclasses thereof. 

-

 

-

    Any available methods that hold for a list object hold for a PlotlyList. 

-

 

-

    Validation checking is preformed upon instantiation. 

-

 

-

    Valid entry types: empty PlotlyDict or dict only. 

-

 

-

 

-

    """ 

-

 

-

    def __init__(self, *args): 

-

        super(PlotlyList, self).__init__(*args) 

-

        if args and isinstance(args[0], dict): 

-

            raise exceptions.PlotlyListEntryError( 

-

                obj=self, 

-

                index=0, 

-

                notes="Just like a `list`, `{name}` must be instantiated with " 

-

                      "a *single* collection.\n" 

-

                      "In other words these are OK:\n" 

-

                      ">>> {name}()\n" 

-

                      ">>> {name}([])\n" 

-

                      ">>> {name}([dict()])\n" 

-

                      ">>> {name}([dict(), dict()])\n" 

-

                      "However, these don't make sense:\n" 

-

                      ">>> {name}(dict())\n" 

-

                      ">>> {name}(dict(), dict())" 

-

                      "".format(name=self.__class__.__name__) 

-

            ) 

-

        self.validate() 

-

        if self.__class__.__name__ == 'PlotlyList': 

-

            warnings.warn("\nThe PlotlyList class is a base class of " 

-

                          "list-like graph_objs.\nIt is not meant to be a " 

-

                          "user interface.") 

-

 

-

    def to_graph_objs(self, caller=True): 

-

        """Change any nested collections to subclasses of PlotlyDict/List. 

-

 

-

        Procedure: 

-

            1. Attempt to convert all entries to a subclass of PlotlyDict. 

-

            2. Call `to_graph_objects` on each of these entries. 

-

 

-

        """ 

-

        for index, entry in enumerate(self): 

-

            if isinstance(entry, PlotlyDict): 

-

                try: 

-

                    entry.to_graph_objs(caller=False) 

-

                except (exceptions.PlotlyGraphObjectError) as err: 

-

                    err.add_to_error_path(index) 

-

                    err.prepare() 

-

                    raise  # re-raise current exception 

-

            else: 

-

                raise exceptions.PlotlyListEntryError(obj=self, 

-

                                                      index=index, 

-

                                                      entry=entry) 

-

 

-

 

-

    def update(self, changes, make_copies=False): 

-

        """Update current list with changed_list, which must be iterable. 

-

        The 'changes' should be a list of dictionaries, however, 

-

        it is permitted to be a single dict object. 

-

 

-

        Because mutable objects contain references to their values, updating 

-

        multiple items in a list will cause the items to all reference the same 

-

        original set of objects. To change this behavior add 

-

        `make_copies=True` which makes deep copies of the update items and 

-

        therefore break references.  

-

 

-

        """ 

-

        if isinstance(changes, dict): 

-

            changes = [changes] 

-

        self.to_graph_objs() 

-

        for index in range(len(self)): 

-

            try: 

-

                update = changes[index % len(changes)] 

-

            except ZeroDivisionError: 

-

                pass 

-

            else: 

-

                if make_copies: 

-

                    self[index].update(copy.deepcopy(update)) 

-

                else: 

-

                    self[index].update(update) 

-

 

-

 

-

    def strip_style(self): 

-

        """Strip style from the current representation. 

-

 

-

        All PlotlyDicts and PlotlyLists are guaranteed to survive the 

-

        stripping process, though they made be left empty. This is allowable. 

-

 

-

        Keys that will be stripped in this process are tagged with 

-

        `'type': 'style'` in the INFO dictionary listed in graph_objs_meta.py. 

-

 

-

        This process first attempts to convert nested collections from dicts 

-

        or lists to subclasses of PlotlyList/PlotlyDict. This process forces 

-

        a validation, which may throw exceptions. 

-

 

-

        Then, each of these objects call `strip_style` on themselves and so 

-

        on, recursively until the entire structure has been validated and 

-

        stripped. 

-

 

-

        """ 

-

        self.to_graph_objs() 

-

        for plotly_dict in self: 

-

            plotly_dict.strip_style() 

-

 

-

    def get_data(self): 

-

        """Returns the JSON for the plot with non-data elements stripped.""" 

-

        self.to_graph_objs() 

-

        l = list() 

-

        for _plotlydict in self: 

-

            l += [_plotlydict.get_data()] 

-

        del_indicies = [index for index, item in enumerate(self) 

-

                        if len(item) == 0] 

-

        del_ct = 0 

-

        for index in del_indicies: 

-

            del self[index - del_ct] 

-

            del_ct += 1 

-

        return l 

-

 

-

    def validate(self, caller=True): 

-

        """Recursively check the validity of the entries in a PlotlyList. 

-

 

-

        PlotlyList may only contain suclasses of PlotlyDict, or dictionary-like 

-

        objects that can be re-instantiated as subclasses of PlotlyDict. 

-

 

-

        The validation process first requires that all nested collections be 

-

        converted to the appropriate subclass of PlotlyDict/PlotlyList. Then, 

-

        each of these objects call `validate` and so on, recursively, 

-

        until the entire list has been validated. 

-

 

-

        """ 

-

        if caller:  # change everything to PlotlyList/Dict objects 

-

            try: 

-

                self.to_graph_objs() 

-

            except exceptions.PlotlyGraphObjectError as err: 

-

                err.prepare() 

-

                raise 

-

        for index, entry in enumerate(self): 

-

            if isinstance(entry, PlotlyDict): 

-

                try: 

-

                    entry.validate(caller=False) 

-

                except exceptions.PlotlyGraphObjectError as err: 

-

                    err.add_to_error_path(index) 

-

                    err.prepare() 

-

                    raise 

-

            else: 

-

                raise exceptions.PlotlyGraphObjectError(  # TODO!!! 

-

                    message="uh-oh, this error shouldn't have happenend.", 

-

                    plain_message="uh-oh, this error shouldn't have happenend.", 

-

                    path=[index], 

-

                ) 

-

 

-

    def to_string(self, level=0, indent=4, eol='\n', pretty=True, max_chars=80): 

-

        """Returns a formatted string showing graph_obj constructors. 

-

 

-

        Example: 

-

 

-

            print obj.to_string() 

-

 

-

        Keyword arguments: 

-

        level (default = 0) -- set number of indentations to start with 

-

        indent (default = 4) -- set indentation amount 

-

        eol (default = '\n') -- set end of line character(s) 

-

        pretty (default = True) -- curtail long list output with a '...' 

-

        max_chars (default = 80) -- set max characters per line 

-

 

-

        """ 

-

        self.to_graph_objs() 

-

        if not len(self): 

-

            return "{name}()".format(name=self.__class__.__name__) 

-

        string = "{name}([{eol}{indent}".format( 

-

            name=self.__class__.__name__, 

-

            eol=eol, 

-

            indent=' ' * indent * (level + 1)) 

-

        for index, entry in enumerate(self): 

-

            string += entry.to_string(level=level+1, 

-

                                      indent=indent, 

-

                                      eol=eol, 

-

                                      pretty=pretty, 

-

                                      max_chars=max_chars) 

-

            if index < len(self) - 1: 

-

                string += ",{eol}{indent}".format( 

-

                    eol=eol, 

-

                    indent=' ' * indent * (level + 1)) 

-

        string += "{eol}{indent}])".format(eol=eol, indent=' ' * indent * level) 

-

        return string 

-

 

-

    def get_ordered(self, caller=True): 

-

        if caller: 

-

            try: 

-

                self.to_graph_objs(caller=False) 

-

            except exceptions.PlotlyGraphObjectError as err: 

-

                err.add_note("Could not order list because it could not be " 

-

                             "converted to a valid graph object.") 

-

                err.prepare() 

-

                raise 

-

        ordered_list = [] 

-

        for index, entry in enumerate(self): 

-

            ordered_list += [entry.get_ordered()] 

-

        return ordered_list 

-

 

-

 

-

    def force_clean(self, caller=True): 

-

        """Attempts to convert to graph_objs and calls force_clean() on entries. 

-

 

-

        Calling force_clean() on a PlotlyList will ensure that the object is 

-

        valid and may be sent to plotly. This process will remove any entries 

-

        that end up with a length == 0. It will also remove itself from 

-

        enclosing trivial structures if it is enclosed by a collection with 

-

        length 1, meaning the data is the ONLY object in the collection. 

-

 

-

        Careful! This will delete any invalid entries *silently*. 

-

 

-

        """ 

-

        if caller: 

-

            self.to_graph_objs()  # TODO add error handling here! 

-

        for entry in self: 

-

            entry.force_clean(caller=False) 

-

        del_indicies = [index for index, item in enumerate(self) 

-

                        if len(item) == 0] 

-

        del_ct = 0 

-

        for index in del_indicies: 

-

            del self[index - del_ct] 

-

            del_ct += 1 

-

 

-

@six.add_metaclass(DictMeta) 

-

class PlotlyDict(dict): 

-

    """A base dict class for all objects that style a figure in plotly. 

-

 

-

    A PlotlyDict can be instantiated like any dict object. This class 

-

    offers some useful recursive methods that can be used by higher-level 

-

    subclasses and containers so long as all plot objects are instantiated 

-

    as a subclass of PlotlyDict. Each PlotlyDict should be instantiated 

-

    with a `kind` keyword argument. This defines the special _info 

-

    dictionary for the object. 

-

 

-

    Any available methods that hold for a dict hold for a PlotlyDict. 

-

 

-

    """ 

-

 

-

    def __init__(self, *args, **kwargs): 

-

        class_name = self.__class__.__name__ 

-

        super(PlotlyDict, self).__init__(*args, **kwargs) 

-

        if issubclass(NAME_TO_CLASS[class_name], PlotlyTrace): 

-

            if (class_name != 'PlotlyTrace') and (class_name != 'Trace'): 

-

                self['type'] = NAME_TO_KEY[class_name] 

-

        self.validate() 

-

        if self.__class__.__name__ == 'PlotlyDict': 

-

            warnings.warn("\nThe PlotlyDict class is a base class of " 

-

                          "dictionary-like graph_objs.\nIt is not meant to be " 

-

                          "a user interface.") 

-

 

-

    def update(self, dict1=None, **dict2): 

-

        """Update current dict with dict1 and then dict2. 

-

 

-

        This recursively updates the structure of the original dictionary-like 

-

        object with the new entries in the second and third objects. This 

-

        allows users to update with large, nested structures. 

-

 

-

        Note, because the dict2 packs up all the keyword arguments, you can 

-

        specify the changes as a list of keyword agruments. 

-

 

-

        Examples: 

-

        # update with dict 

-

        obj = Layout(title='my title', xaxis=XAxis(range=[0,1], domain=[0,1])) 

-

        update_dict = dict(title='new title', xaxis=dict(domain=[0,.8])) 

-

        obj.update(update_dict) 

-

        obj 

-

        {'title': 'new title', 'xaxis': {'range': [0,1], 'domain': [0,.8]}} 

-

 

-

        # update with list of keyword arguments 

-

        obj = Layout(title='my title', xaxis=XAxis(range=[0,1], domain=[0,1])) 

-

        obj.update(title='new title', xaxis=dict(domain=[0,.8])) 

-

        obj 

-

        {'title': 'new title', 'xaxis': {'range': [0,1], 'domain': [0,.8]}} 

-

 

-

        This 'fully' supports duck-typing in that the call signature is 

-

        identical, however this differs slightly from the normal update 

-

        method provided by Python's dictionaries. 

-

 

-

        """ 

-

        self.to_graph_objs() 

-

 

-

        if dict1 is not None: 

-

            for key, val in list(dict1.items()): 

-

                if key in self: 

-

                    if isinstance(self[key], (PlotlyDict, PlotlyList)): 

-

                        self[key].update(val) 

-

                    else: 

-

                        self[key] = val 

-

                else: 

-

                    self[key] = val 

-

 

-

        if len(dict2): 

-

            for key, val in list(dict2.items()): 

-

                if key in self: 

-

                    if isinstance(self[key], (PlotlyDict, PlotlyList)): 

-

                        self[key].update(val) 

-

                    else: 

-

                        self[key] = val 

-

                else: 

-

                    self[key] = val 

-

        self.to_graph_objs() 

-

 

-

    def strip_style(self): 

-

        """Strip style from the current representation. 

-

 

-

        All PlotlyDicts and PlotlyLists are guaranteed to survive the 

-

        stripping process, though they made be left empty. This is allowable. 

-

 

-

        Keys that will be stripped in this process are tagged with 

-

        `'type': 'style'` in the INFO dictionary listed in graph_objs_meta.py. 

-

 

-

        This process first attempts to convert nested collections from dicts 

-

        or lists to subclasses of PlotlyList/PlotlyDict. This process forces 

-

        a validation, which may throw exceptions. 

-

 

-

        Then, each of these objects call `strip_style` on themselves and so 

-

        on, recursively until the entire structure has been validated and 

-

        stripped. 

-

 

-

        """ 

-

        self.to_graph_objs() 

-

        obj_key = NAME_TO_KEY[self.__class__.__name__] 

-

        keys = list(self.keys()) 

-

        for key in keys: 

-

            if isinstance(self[key], (PlotlyDict, PlotlyList)): 

-

                self[key].strip_style() 

-

            else: 

-

                try: 

-

                    if INFO[obj_key][key]['type'] == 'style': 

-

                        if isinstance(self[key], six.string_types): 

-

                            del self[key] 

-

                        elif not hasattr(self[key], '__iter__'): 

-

                            del self[key] 

-

                except KeyError:  # TODO: Update the JSON 

-

                    # print "'type' not in {0} for {1}".format(obj_key, key) 

-

                    pass 

-

 

-

    def get_data(self): 

-

        """Returns the JSON for the plot with non-data elements stripped.""" 

-

        self.to_graph_objs() 

-

        class_name = self.__class__.__name__ 

-

        obj_key = NAME_TO_KEY[class_name] 

-

        d = dict() 

-

        for key, val in list(self.items()): 

-

            if isinstance(val, (PlotlyDict, PlotlyList)): 

-

                d[key] = val.get_data() 

-

            else: 

-

                try: 

-

                    if INFO[obj_key][key]['type'] == 'data':  # TODO: Update the JSON 

-

                        d[key] = val 

-

                except KeyError: 

-

                    pass 

-

        keys = list(d.keys()) 

-

        for key in keys: 

-

            if isinstance(d[key], (dict, list)): 

-

                if len(d[key]) == 0: 

-

                    del d[key] 

-

        if len(d) == 1: 

-

            d = list(d.values())[0] 

-

        return d 

-

 

-

    def to_graph_objs(self, caller=True): 

-

        """Walk obj, convert dicts and lists to plotly graph objs. 

-

 

-

        For each key in the object, if it corresponds to a special key that 

-

        should be associated with a graph object, the ordinary dict or list 

-

        will be reinitialized as a special PlotlyDict or PlotlyList of the 

-

        appropriate `kind`. 

-

 

-

        """ 

-

        info_key = NAME_TO_KEY[self.__class__.__name__] 

-

        keys = self.keys() 

-

        updated_keys = graph_objs_tools.update_keys(keys) 

-

        for k_old, k_new in zip(keys, updated_keys): 

-

            if k_old != k_new: 

-

                self[k_new] = self.pop(k_old) 

-

                warnings.warn( 

-

                    "\n" 

-

                    "The key, '{old}', has been depreciated, it's been " 

-

                    "converted to '{new}'. You should change your code to use " 

-

                    "'{new}' in the future." 

-

                    "".format(old=k_old, new=k_new) 

-

                ) 

-

        for key in updated_keys: 

-

            if isinstance(self[key], (PlotlyDict, PlotlyList)): 

-

                try: 

-

                    self[key].to_graph_objs(caller=False) 

-

                except exceptions.PlotlyGraphObjectError as err: 

-

                    err.add_to_error_path(key) 

-

                    err.prepare() 

-

                    raise 

-

            elif key in INFO[info_key] and 'type' in INFO[info_key][key]: 

-

                if INFO[info_key][key]['type'] == 'object': 

-

                    class_name = KEY_TO_NAME[key] 

-

                    obj = NAME_TO_CLASS[class_name]()  # gets constructor 

-

                    if isinstance(obj, PlotlyDict): 

-

                        if not isinstance(self[key], dict): 

-

                            try: 

-

                                val_types = INFO[info_key][key]['val_types'] 

-

                            except KeyError: 

-

                                val_types = 'undocumented' 

-

                            raise exceptions.PlotlyDictValueError( 

-

                                obj=self, 

-

                                key=key, 

-

                                value=self[key], 

-

                                val_types=val_types, 

-

                                notes="value needs to be dictionary-like" 

-

                            ) 

-

                        for k, v in list(self.pop(key).items()): 

-

                            obj[k] = v  # finish up momentarily... 

-

                    else:  # if not PlotlyDict, it MUST be a PlotlyList 

-

                        if not isinstance(self[key], list): 

-

                            try: 

-

                                val_types = INFO[info_key][key]['val_types'] 

-

                            except KeyError: 

-

                                val_types = 'undocumented' 

-

                            raise exceptions.PlotlyDictValueError(  # TODO!!! 

-

                                obj=self, 

-

                                key=key, 

-

                                value=self[key], 

-

                                val_types=val_types, 

-

                                notes="value needs to be list-like" 

-

                            ) 

-

                        obj += self.pop(key) 

-

                    try: 

-

                        obj.to_graph_objs(caller=False) 

-

                    except exceptions.PlotlyGraphObjectError as err: 

-

                        err.add_to_error_path(key) 

-

                        err.prepare() 

-

                        raise 

-

                    self[key] = obj  # whew! made it! 

-

 

-

    def validate(self, caller=True):  # TODO: validate values too? 

-

        """Recursively check the validity of the keys in a PlotlyDict. 

-

 

-

        The valid keys constitute the entries in each object 

-

        dictionary in INFO stored in graph_objs_meta.py. 

-

 

-

        The validation process first requires that all nested collections be 

-

        converted to the appropriate subclass of PlotlyDict/PlotlyList. Then, 

-

        each of these objects call `validate` and so on, recursively, 

-

        until the entire object has been validated. 

-

 

-

        """ 

-

        if caller:  # change everything to 'checkable' objs 

-

            try: 

-

                self.to_graph_objs(caller=False) 

-

            except exceptions.PlotlyGraphObjectError as err: 

-

                err.prepare() 

-

                raise 

-

        obj_key = NAME_TO_KEY[self.__class__.__name__] 

-

        for key, val in list(self.items()): 

-

            if isinstance(val, (PlotlyDict, PlotlyList)): 

-

                try: 

-

                    val.validate(caller=False) 

-

                except exceptions.PlotlyGraphObjectError as err: 

-

                    err.add_to_error_path(key) 

-

                    err.prepare() 

-

                    raise 

-

            else: 

-

                if key in INFO[obj_key]: 

-

                    if 'type' not in INFO[obj_key][key]: 

-

                        continue  # TODO: 'type' may not be documented yet! 

-

                    if INFO[obj_key][key]['type'] == 'object': 

-

                        try: 

-

                            val_types = INFO[obj_key][key]['val_types'] 

-

                        except KeyError: 

-

                            val_types = 'undocumented' 

-

                        raise exceptions.PlotlyDictValueError( 

-

                            obj=self, 

-

                            key=key, 

-

                            value=val, 

-

                            val_types=val_types 

-

                        ) 

-

                else: 

-

                    matching_objects = [obj for obj in INFO if key in INFO[obj]] 

-

                    notes = '' 

-

                    if len(matching_objects): 

-

                        notes += "That key is valid only in these objects:\n\n" 

-

                        for obj in matching_objects: 

-

                            notes += "\t{0}".format(KEY_TO_NAME[obj]) 

-

                            try: 

-

                                notes += '({0}="{1}")\n'.format( 

-

                                    repr(key), INFO[obj][key]['val_types']) 

-

                            except KeyError: 

-

                                notes += '({0}="..")\n'.format(repr(key)) 

-

                        notes.expandtabs() 

-

                    else: 

-

                        notes += ("Couldn't find uses for key: {0}\n\n" 

-

                                  "".format(repr(key))) 

-

                    raise exceptions.PlotlyDictKeyError(obj=self, 

-

                                                        key=key, 

-

                                                        notes=notes) 

-

 

-

    def to_string(self, level=0, indent=4, eol='\n', pretty=True, max_chars=80): 

-

        """Returns a formatted string showing graph_obj constructors. 

-

 

-

        Example: 

-

 

-

            print obj.to_string() 

-

 

-

        Keyword arguments: 

-

        level (default = 0) -- set number of indentations to start with 

-

        indent (default = 4) -- set indentation amount 

-

        eol (default = '\n') -- set end of line character(s) 

-

        pretty (default = True) -- curtail long list output with a '...' 

-

        max_chars (default = 80) -- set max characters per line 

-

 

-

        """ 

-

        self.to_graph_objs()  # todo, consider catching and re-raising? 

-

        if not len(self): 

-

            return "{name}()".format(name=self.__class__.__name__) 

-

        string = "{name}(".format(name=self.__class__.__name__) 

-

        index = 0 

-

        obj_key = NAME_TO_KEY[self.__class__.__name__] 

-

        for key in INFO[obj_key]:  # this sets the order of the keys! nice. 

-

            if key in self: 

-

                string += "{eol}{indent}{key}=".format( 

-

                    eol=eol, 

-

                    indent=' ' * indent * (level+1), 

-

                    key=key) 

-

                try: 

-

                    string += self[key].to_string(level=level+1, 

-

                                                  indent=indent, 

-

                                                  eol=eol, 

-

                                                  pretty=pretty, 

-

                                                  max_chars=max_chars) 

-

                except AttributeError: 

-

                    val = repr(self[key]) 

-

                    val_chars = max_chars - (indent*(level+1)) - (len(key)+1) 

-

                    if pretty and (len(val) > val_chars): 

-

                        string += val[:val_chars - 5] + '...' + val[-1] 

-

                    else: 

-

                        string += val 

-

                if index < len(self) - 1: 

-

                    string += "," 

-

                index += 1 

-

                if index == len(self): 

-

                    break 

-

        string += "{eol}{indent})".format(eol=eol, indent=' ' * indent * level) 

-

        return string 

-

 

-

    def get_ordered(self, caller=True): 

-

        if caller:  # change everything to 'order-able' objs 

-

            try: 

-

                self.to_graph_objs(caller=False) 

-

            except exceptions.PlotlyGraphObjectError as err: 

-

                err.add_note("dictionary could not be ordered because it " 

-

                             "could not be converted to a valid plotly graph " 

-

                             "object.") 

-

                err.prepare() 

-

                raise 

-

        obj_type = NAME_TO_KEY[self.__class__.__name__] 

-

        ordered_dict = OrderedDict() 

-

        # grab keys like xaxis1, xaxis2, etc... 

-

        unordered_keys = [key for key in self if key not in INFO[obj_type]] 

-

        for key in INFO[obj_type]: 

-

            if key in self: 

-

                if isinstance(self[key], (PlotlyDict, PlotlyList)): 

-

                    ordered_dict[key] = self[key].get_ordered(caller=False) 

-

                else: 

-

                    ordered_dict[key] = self[key] 

-

        for key in unordered_keys: 

-

            if isinstance(self[key], (PlotlyDict, PlotlyList)): 

-

                ordered_dict[key] = self[key].get_ordered(caller=False) 

-

            else: 

-

                ordered_dict[key] = self[key] 

-

        return ordered_dict 

-

 

-

 

-

    def force_clean(self, caller=True): 

-

        """Attempts to convert to graph_objs and call force_clean() on values. 

-

 

-

        Calling force_clean() on a PlotlyDict will ensure that the object is 

-

        valid and may be sent to plotly. This process will also remove any 

-

        entries that end up with a length == 0. 

-

 

-

        Careful! This will delete any invalid entries *silently*. 

-

 

-

        """ 

-

        obj_key = NAME_TO_KEY[self.__class__.__name__] 

-

        if caller: 

-

            self.to_graph_objs(caller=False) 

-

        del_keys = [key for key in self if str(key) not in INFO[obj_key]] 

-

        for key in del_keys: 

-

            del self[key] 

-

        keys = list(self.keys()) 

-

        for key in keys: 

-

            try: 

-

                self[key].force_clean(caller=False)  # TODO: add error handling 

-

            except AttributeError: 

-

                pass 

-

            if isinstance(self[key], (dict, list)): 

-

                if len(self[key]) == 0: 

-

                    del self[key]  # clears empty collections! 

-

            elif self[key] is None: 

-

                del self[key] 

-

 

-

 

-

class Data(PlotlyList): 

-

    """A list of traces to be shown on a plot/graph. 

-

 

-

    Any operation that can be done with a standard list may be used with Data. 

-

    Instantiation requires an iterable (just like list does), for example: 

-

 

-

    Data([Scatter(), Heatmap(), Box()]) 

-

 

-

    Valid entry types: (dict or any subclass of Trace, i.e., Scatter, Box, etc.) 

-

 

-

    """ 

-

    def to_graph_objs(self, caller=True):  # TODO TODO TODO! check logic! 

-

        """Change any nested collections to subclasses of PlotlyDict/List. 

-

 

-

        Procedure: 

-

            1. Attempt to convert all entries to a subclass of PlotlyTrace. 

-

            2. Call `to_graph_objects` on each of these entries. 

-

 

-

        """ 

-

        for index, entry in enumerate(self): 

-

            if isinstance(entry, PlotlyDict): 

-

                self[index] = NAME_TO_CLASS[entry.__class__.__name__](entry) 

-

            elif isinstance(entry, dict): 

-

                if 'type' not in entry:  # assume 'scatter' if not given 

-

                    entry['type'] = 'scatter' 

-

                try: 

-

                    obj_name = KEY_TO_NAME[entry['type']] 

-

                except KeyError: 

-

                    raise exceptions.PlotlyDataTypeError( 

-

                        obj=self, 

-

                        index=index 

-

                    ) 

-

                obj = NAME_TO_CLASS[obj_name]()  # don't hide if KeyError! 

-

                for k, v in list(entry.items()): 

-

                    obj[k] = v 

-

                self[index] = obj 

-

            if not isinstance(self[index], PlotlyTrace):  # Trace ONLY!!! 

-

                raise exceptions.PlotlyListEntryError( 

-

                    obj=self, 

-

                    index=index, 

-

                    notes="The entry could not be converted into a PlotlyTrace " 

-

                          "object (e.g., Scatter, Heatmap, Bar, etc).", 

-

                ) 

-

        super(Data, self).to_graph_objs(caller=caller) 

-

 

-

 

-

class Annotations(PlotlyList): 

-

    """A list-like object to contain all figure notes. 

-

 

-

    Any operation that can be done with a standard list may be used with 

-

    Annotations. Instantiation requires an iterable (just like list does), 

-

    for example: 

-

 

-

    Annotations([Annotation(), Annotation(), Annotation()]) 

-

 

-

    This Annotations list is validated upon instantiation, meaning exceptions 

-

    will be thrown if any invalid entries are found. 

-

 

-

    Valid entry types: (dict or Annotation) 

-

 

-

    For help on Annotation, run `help(plotly.graph_objs.Annotation)` 

-

 

-

    """ 

-

    def to_graph_objs(self, caller=True): 

-

        """Change any nested collections to subclasses of PlotlyDict/List. 

-

 

-

        Procedure: 

-

            1. Attempt to convert all entries to a subclass of PlotlyDict. 

-

            2. Call `to_graph_objects` on each of these entries. 

-

 

-

        """ 

-

        for index, entry in enumerate(self): 

-

            if isinstance(entry, (PlotlyDict, PlotlyList)): 

-

                if not isinstance(entry, Annotation): 

-

                    raise exceptions.PlotlyListEntryError( 

-

                        obj=self, 

-

                        index=index, 

-

                        notes="The entry could not be converted into an " 

-

                              "Annotation object because it was already a " 

-

                              "different kind of graph object.", 

-

                    ) 

-

            elif isinstance(entry, dict): 

-

                obj = Annotation() 

-

                for k, v in list(entry.items()): 

-

                    obj[k] = v 

-

                self[index] = obj 

-

            else: 

-

                raise exceptions.PlotlyListEntryError( 

-

                    obj=self, 

-

                    index=index, 

-

                    notes="The entry could not be converted into an Annotation " 

-

                          "object because it was not a dictionary.", 

-

                ) 

-

        super(Annotations, self).to_graph_objs(caller=caller) 

-

 

-

 

-

class PlotlyTrace(PlotlyDict): 

-

    """A general data class for plotly. 

-

 

-

    The PlotlyTrace object is not meant for user interaction. It's sole 

-

    purpose is to improve the structure of the object hierarchy established 

-

    in this module. 

-

 

-

    Users should work with the subclasses of PlotlyTrace: Scatter, Box, Bar, 

-

    Heatmap, etc. 

-

 

-

    For help with these subclasses, run: 

-

    `help(plotly.graph_objs.Obj)` where Obj == Scatter, Box, Bar, Heatmap, etc. 

-

 

-

    """ 

-

    def __init__(self, *args, **kwargs): 

-

        super(PlotlyTrace, self).__init__(*args, **kwargs) 

-

        if self.__class__.__name__ == 'PlotlyTrace': 

-

            warnings.warn("\nThe PlotlyTrace class is a base class of " 

-

                          "dictionary-like plot types.\nIt is not meant to be " 

-

                          "a user interface.") 

-

 

-

    def to_string(self, level=0, indent=4, eol='\n', pretty=True, max_chars=80): 

-

        """Returns a formatted string showing graph_obj constructors. 

-

 

-

        Example: 

-

 

-

            print obj.to_string() 

-

 

-

        Keyword arguments: 

-

        level (default = 0) -- set number of indentations to start with 

-

        indent (default = 4) -- set indentation amount 

-

        eol (default = '\n') -- set end of line character(s) 

-

        pretty (default = True) -- curtail long list output with a '...' 

-

        max_chars (default = 80) -- set max characters per line 

-

 

-

        """ 

-

        self.to_graph_objs() 

-

        if self.__class__.__name__ != "Trace": 

-

            trace_type = self.pop('type') 

-

            string = super(PlotlyTrace, self).to_string(level=level, 

-

                                                        indent=indent, 

-

                                                        eol=eol, 

-

                                                        pretty=pretty, 

-

                                                        max_chars=max_chars) 

-

            self['type'] = trace_type 

-

        else: 

-

            string = super(PlotlyTrace, self).to_string(level=level, 

-

                                                        indent=indent, 

-

                                                        eol=eol, 

-

                                                        pretty=pretty, 

-

                                                        max_chars=max_chars) 

-

        return string 

-

 

-

 

-

class Trace(PlotlyTrace): 

-

    """A general data class for plotly. Never validated... 

-

 

-

    This class should be used only for the right reason. This class does not 

-

    do much validation because plotly usually accepts more trace specifiers 

-

    and more value type varieties, e.g., 'x', 'y', 'r', 't', marker = [ 

-

    array], etc. 

-

 

-

    If you are getting errors locally, you might try using this case if 

-

    you're sure that what you're attempting to plot is valid. 

-

 

-

    Also, when getting figures from plotly, you may get back `Trace` types if 

-

    the figure was constructed with data objects that don't fall into any of 

-

    the class categorizations that are defined in this api. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Area(PlotlyTrace): 

-

    """A dictionary-like object for representing an area chart in plotly. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Bar(PlotlyTrace): 

-

    """A dictionary-like object for representing a bar chart in plotly. 

-

 

-

    Example: 

-

 

-

    py.plot([Bar(x=['yesterday', 'today', 'tomorrow'], y=[5, 4, 10])]) 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Box(PlotlyTrace): 

-

    """A dictionary-like object for representing a box plot in plotly. 

-

 

-

    Example: 

-

 

-

        py.plot([Box(name='boxy', y=[1,3,9,2,4,2,3,5,2])]) 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Contour(PlotlyTrace): 

-

    """A dictionary-like object for representing a contour plot in plotly. 

-

 

-

    Example: 

-

 

-

        z = [[0, 1, 0, 1, 0], 

-

             [1, 0, 1, 0, 1], 

-

             [0, 1, 0, 1, 0],] 

-

        y = ['a', 'b', 'c'] 

-

        x = [1, 2, 3, 4, 5] 

-

        py.plot([Contour(z=z, x=x, y=y)]) 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Heatmap(PlotlyTrace): 

-

    """A dictionary-like object for representing a heatmap in plotly. 

-

 

-

    Example: 

-

 

-

        z = [[0, 1, 0, 1, 0], 

-

             [1, 0, 1, 0, 1], 

-

             [0, 1, 0, 1, 0],] 

-

        y = ['a', 'b', 'c'] 

-

        x = [1, 2, 3, 4, 5] 

-

        py.plot([Heatmap(z=z, x=x, y=y)]) 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Histogram(PlotlyTrace): 

-

    """A dictionary-like object for representing a histogram plot in plotly. 

-

 

-

    Example: 

-

        # make a histogram along xaxis... 

-

        py.plot([Histogram(x=[1,1,2,3,2,3,3])]) 

-

 

-

        # make a histogram along yaxis... 

-

        py.plot([Histogram(y=[1,1,2,3,2,3,3], orientation='h')]) 

-

 

-

    """ 

-

 

-

 

-

class Histogram2d(PlotlyTrace): 

-

    """A dictionary-like object for representing a histogram2d plot in plotly. 

-

 

-

    Example: 

-

 

-

        import numpy as np 

-

        x = np.random.randn(500) 

-

        y = np.random.randn(500)+1 

-

        py.iplot([Histogram2d(x=x, y=y)]) 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Histogram2dContour(PlotlyTrace): 

-

    """A dict-like object for representing a histogram2d-contour plot in plotly. 

-

 

-

    Example: 

-

 

-

        import numpy as np 

-

        x = np.random.randn(500) 

-

        y = np.random.randn(500)+1 

-

        py.iplot([Histogram2dcountour(x=x, y=y)]) 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Scatter(PlotlyTrace): 

-

    """A dictionary-like object for representing a scatter plot in plotly. 

-

 

-

    Example: 

-

 

-

        py.plot([Scatter(name='tacters', x=[1,4,2,3], y=[1,6,2,1])]) 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class AngularAxis(PlotlyDict): 

-

    """A  dictionary-like object for representing an angular axis in plotly. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class RadialAxis(PlotlyDict): 

-

    """A  dictionary-like object for representing an angular axis in plotly. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Annotation(PlotlyDict): 

-

    """A dictionary-like object for representing an annotation in plotly. 

-

 

-

    Annotations appear as notes on the final figure. You can set all the 

-

    features of the annotation text, background color, and location. 

-

    Additionally, these notes can be anchored to actual data or the page for 

-

    help with location after pan-and-zoom actions. 

-

 

-

    This object is validated upon instantiation, therefore, you may see 

-

    exceptions getting thrown. These are intended to help users find the 

-

    origin of errors faster. The errors will usually contain information that 

-

    can be used to remedy the problem. 

-

 

-

    Example: 

-

 

-

        note = Annotation(text='what i want this to say is:<br>THIS!', 

-

                          x=0, 

-

                          y=0, 

-

                          xref='paper', 

-

                          yref='paper, 

-

                          yanchor='bottom', 

-

                          xanchor='left') 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class ColorBar(PlotlyDict):  # TODO: ? 

-

    """A dictionary-like object for representing a color bar in plotly. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Contours(PlotlyDict):  # TODO: ? 

-

    """A dictionary-like object for representing a contours object in plotly. 

-

 

-

    This object exists inside definitions for a contour plot. 

-

 

-

    """ 

-

 

-

class ErrorX(PlotlyDict): 

-

    """A dictionary-like object for representing a set of errorx bars in plotly. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class ErrorY(PlotlyDict): 

-

    """A dictionary-like object for representing a set of errory bars in plotly. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Figure(PlotlyDict): 

-

    """A dictionary-like object representing a figure to be rendered in plotly. 

-

 

-

    This is the container for all things to be rendered in a figure. 

-

 

-

    For help with setting up subplots, run: 

-

    `help(plotly.tools.get_subplots)` 

-

 

-

    """ 

-

    def __init__(self, *args, **kwargs): 

-

        if len(args): 

-

            if ('data' not in kwargs) and ('data' not in args[0]): 

-

                kwargs['data'] = Data() 

-

            if ('layout' not in kwargs) and ('layout' not in args[0]): 

-

                kwargs['layout'] = Layout() 

-

        else: 

-

            if 'data' not in kwargs: 

-

                kwargs['data'] = Data() 

-

            if 'layout' not in kwargs: 

-

                kwargs['layout'] = Layout() 

-

        super(Figure, self).__init__(*args, **kwargs) 

-

 

-

 

-

class Font(PlotlyDict): 

-

    """A dictionary-like object representing details about font style. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Layout(PlotlyDict): 

-

    """A dictionary-like object holding plot settings for plotly figures. 

-

 

-

    """ 

-

    def __init__(self, *args, **kwargs): 

-

        super(Layout, self).__init__(*args, **kwargs) 

-

 

-

    def to_graph_objs(self, caller=True): 

-

        """Walk obj, convert dicts and lists to plotly graph objs. 

-

 

-

        For each key in the object, if it corresponds to a special key that 

-

        should be associated with a graph object, the ordinary dict or list 

-

        will be reinitialized as a special PlotlyDict or PlotlyList of the 

-

        appropriate `kind`. 

-

 

-

        """ 

-

        keys = list(self.keys()) 

-

        for key in keys: 

-

            if key[:5] in ['xaxis', 'yaxis']:  # allows appended integers! 

-

                try: 

-

                    axis_int = int(key[5:])  # may raise ValueError 

-

                    if axis_int == 0: 

-

                        continue  # xaxis0 and yaxis0 are not valid keys... 

-

                except ValueError: 

-

                    continue  # not an XAxis or YAxis object after all 

-

                if isinstance(self[key], dict): 

-

                    if key[:5] == 'xaxis': 

-

                        obj = XAxis() 

-

                    else: 

-

                        obj = YAxis() 

-

                    for k, v in list(self.pop(key).items()): 

-

                        obj[k] = v 

-

                    self[key] = obj  # call to super will call 'to_graph_objs' 

-

        super(Layout, self).to_graph_objs(caller=caller) 

-

 

-

    def to_string(self, level=0, indent=4, eol='\n', pretty=True, max_chars=80): 

-

        """Returns a formatted string showing graph_obj constructors. 

-

 

-

        Example: 

-

 

-

            print obj.to_string() 

-

 

-

        Keyword arguments: 

-

        level (default = 0) -- set number of indentations to start with 

-

        indent (default = 4) -- set indentation amount 

-

        eol (default = '\n') -- set end of line character(s) 

-

        pretty (default = True) -- curtail long list output with a '...' 

-

        max_chars (default = 80) -- set max characters per line 

-

 

-

        """ 

-

        # TODO: can't call super 

-

        self.to_graph_objs() 

-

        if not len(self): 

-

            return "{name}()".format(name=self.__class__.__name__) 

-

        string = "{name}(".format(name=self.__class__.__name__) 

-

        index = 0 

-

        obj_key = NAME_TO_KEY[self.__class__.__name__] 

-

        for key in INFO[obj_key]: 

-

            if key in self: 

-

                string += "{eol}{indent}{key}=".format( 

-

                    eol=eol, 

-

                    indent=' ' * indent * (level+1), 

-

                    key=key) 

-

                try: 

-

                    string += self[key].to_string(level=level+1, 

-

                                                  indent=indent, 

-

                                                  eol=eol, 

-

                                                  pretty=pretty, 

-

                                                  max_chars=max_chars) 

-

                except AttributeError: 

-

                    val = repr(self[key]) 

-

                    val_chars = max_chars - (indent*(level+1)) - (len(key)+1) 

-

                    if pretty and (len(val) > val_chars): 

-

                        string += val[:val_chars - 5] + '...' + val[-1] 

-

                    else: 

-

                        string += val 

-

                if index < len(self) - 1: 

-

                    string += "," 

-

                index += 1 

-

                if index == len(self): 

-

                    break 

-

        left_over_keys = [key for key in self if key not in INFO[obj_key]] 

-

        left_over_keys.sort() 

-

        for key in left_over_keys: 

-

            string += "{eol}{indent}{key}=".format( 

-

                eol=eol, 

-

                indent=' ' * indent * (level+1), 

-

                key=key) 

-

            try: 

-

                string += self[key].to_string(level=level + 1, 

-

                                              indent=indent, 

-

                                              eol=eol, 

-

                                              pretty=pretty, 

-

                                              max_chars=max_chars) 

-

            except AttributeError: 

-

                string += str(repr(self[key])) 

-

            if index < len(self) - 1: 

-

                string += "," 

-

            index += 1 

-

        string += "{eol}{indent})".format(eol=eol, indent=' ' * indent * level) 

-

        return string 

-

 

-

    def force_clean(self, caller=True):  # TODO: can't make call to super... 

-

        """Attempts to convert to graph_objs and call force_clean() on values. 

-

 

-

        Calling force_clean() on a Layout will ensure that the object is 

-

        valid and may be sent to plotly. This process will also remove any 

-

        entries that end up with a length == 0. 

-

 

-

        Careful! This will delete any invalid entries *silently*. 

-

 

-

        This method differs from the parent (PlotlyDict) method in that it 

-

        must check for an infinite number of possible axis keys, i.e. 'xaxis', 

-

        'xaxis1', 'xaxis2', 'xaxis3', etc. Therefore, it cannot make a call 

-

        to super... 

-

 

-

        """ 

-

        obj_key = NAME_TO_KEY[self.__class__.__name__] 

-

        if caller: 

-

            self.to_graph_objs(caller=False) 

-

        del_keys = [key for key in self if str(key) not in INFO[obj_key]] 

-

        for key in del_keys: 

-

            if (key[:5] == 'xaxis') or (key[:5] == 'yaxis'): 

-

                try: 

-

                    test_if_int = int(key[5:]) 

-

                except ValueError: 

-

                    del self[key] 

-

            else: 

-

                del self[key] 

-

        keys = list(self.keys()) 

-

        for key in keys: 

-

            try: 

-

                self[key].force_clean(caller=False)  # TODO error handling?? 

-

            except AttributeError: 

-

                pass 

-

            if isinstance(self[key], (dict, list)): 

-

                if len(self[key]) == 0: 

-

                    del self[key]  # clears empty collections! 

-

            elif self[key] is None: 

-

                del self[key] 

-

 

-

 

-

class Legend(PlotlyDict): 

-

    """A dictionary-like object representing the legend options for a figure. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Line(PlotlyDict): 

-

    """A dictionary-like object representing the style of a line in plotly. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Marker(PlotlyDict): 

-

    """A dictionary-like object representing marker(s) style in plotly. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Margin(PlotlyDict): 

-

    """A dictionary-like object holding plot margin information. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class Stream(PlotlyDict): 

-

    """A dictionary-like object representing a data stream. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class XAxis(PlotlyDict): 

-

    """A dictionary-like object representing an xaxis in plotly. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class XBins(PlotlyDict): 

-

    """A dictionary-like object representing bin information for a histogram. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class YAxis(PlotlyDict): 

-

    """A dictionary-like object representing a yaxis in plotly. 

-

 

-

    """ 

-

    pass 

-

 

-

 

-

class YBins(PlotlyDict): 

-

    """A dictionary-like object representing bin information for a histogram. 

-

 

-

    """ 

-

    pass 

-

 

-

# finally... define how to map from a class name to an actual class 

-

# mapping: (n->n) 

-

NAME_TO_CLASS = dict( 

-

    PlotlyList=PlotlyList, 

-

    Data=Data, 

-

    Annotations=Annotations, 

-

    PlotlyDict=PlotlyDict, 

-

    PlotlyTrace=PlotlyTrace, 

-

    Area=Area, 

-

    Bar=Bar, 

-

    Box=Box, 

-

    Contour=Contour, 

-

    Heatmap=Heatmap, 

-

    Histogram=Histogram, 

-

    Histogram2d=Histogram2d, 

-

    Histogram2dContour=Histogram2dContour, 

-

    Scatter=Scatter, 

-

    AngularAxis=AngularAxis, 

-

    Annotation=Annotation, 

-

    ColorBar=ColorBar, 

-

    Contours=Contours, 

-

    ErrorX=ErrorX, 

-

    ErrorY=ErrorY, 

-

    Figure=Figure, 

-

    Font=Font, 

-

    Layout=Layout, 

-

    Legend=Legend, 

-

    Line=Line, 

-

    Margin=Margin, 

-

    Marker=Marker, 

-

    RadialAxis=RadialAxis, 

-

    Stream=Stream, 

-

    Trace=Trace, 

-

    XAxis=XAxis, 

-

    XBins=XBins, 

-

    YAxis=YAxis, 

-

    YBins=YBins 

-

) 

- -
-
- - - - - diff --git a/plotly/tests/coverage/plotly_graph_objs_graph_objs_tools.html b/plotly/tests/coverage/plotly_graph_objs_graph_objs_tools.html deleted file mode 100644 index be43bbb4878..00000000000 --- a/plotly/tests/coverage/plotly_graph_objs_graph_objs_tools.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - Coverage for plotly/graph_objs/graph_objs_tools: 88% - - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

- -
-

def update_keys(keys): 

-

    """Change keys we used to support to their new equivalent.""" 

-

    updated_keys = list() 

-

    for key in keys: 

-

        if key in translations: 

-

            updated_keys += [translations[key]] 

-

        else: 

-

            updated_keys += [key] 

-

    return updated_keys 

-

 

-

translations = dict( 

-

    scl="colorscale", 

-

    reversescale="reversescale" 

-

) 

- -
-
- - - - - diff --git a/plotly/tests/coverage/plotly_matplotlylib_mpltools.html b/plotly/tests/coverage/plotly_matplotlylib_mpltools.html deleted file mode 100644 index c47dd56fa3e..00000000000 --- a/plotly/tests/coverage/plotly_matplotlylib_mpltools.html +++ /dev/null @@ -1,1074 +0,0 @@ - - - - - - - - Coverage for plotly/matplotlylib/mpltools: 78% - - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

-

27

-

28

-

29

-

30

-

31

-

32

-

33

-

34

-

35

-

36

-

37

-

38

-

39

-

40

-

41

-

42

-

43

-

44

-

45

-

46

-

47

-

48

-

49

-

50

-

51

-

52

-

53

-

54

-

55

-

56

-

57

-

58

-

59

-

60

-

61

-

62

-

63

-

64

-

65

-

66

-

67

-

68

-

69

-

70

-

71

-

72

-

73

-

74

-

75

-

76

-

77

-

78

-

79

-

80

-

81

-

82

-

83

-

84

-

85

-

86

-

87

-

88

-

89

-

90

-

91

-

92

-

93

-

94

-

95

-

96

-

97

-

98

-

99

-

100

-

101

-

102

-

103

-

104

-

105

-

106

-

107

-

108

-

109

-

110

-

111

-

112

-

113

-

114

-

115

-

116

-

117

-

118

-

119

-

120

-

121

-

122

-

123

-

124

-

125

-

126

-

127

-

128

-

129

-

130

-

131

-

132

-

133

-

134

-

135

-

136

-

137

-

138

-

139

-

140

-

141

-

142

-

143

-

144

-

145

-

146

-

147

-

148

-

149

-

150

-

151

-

152

-

153

-

154

-

155

-

156

-

157

-

158

-

159

-

160

-

161

-

162

-

163

-

164

-

165

-

166

-

167

-

168

-

169

-

170

-

171

-

172

-

173

-

174

-

175

-

176

-

177

-

178

-

179

-

180

-

181

-

182

-

183

-

184

-

185

-

186

-

187

-

188

-

189

-

190

-

191

-

192

-

193

-

194

-

195

-

196

-

197

-

198

-

199

-

200

-

201

-

202

-

203

-

204

-

205

-

206

-

207

-

208

-

209

-

210

-

211

-

212

-

213

-

214

-

215

-

216

-

217

-

218

-

219

-

220

-

221

-

222

-

223

-

224

-

225

-

226

-

227

-

228

-

229

-

230

-

231

-

232

-

233

-

234

-

235

-

236

-

237

-

238

-

239

-

240

-

241

-

242

-

243

-

244

-

245

-

246

-

247

-

248

-

249

-

250

-

251

-

252

-

253

-

254

-

255

-

256

-

257

-

258

-

259

-

260

-

261

-

262

-

263

-

264

-

265

-

266

-

267

-

268

-

269

-

270

-

271

-

272

-

273

-

274

-

275

-

276

-

277

-

278

-

279

-

280

-

281

-

282

-

283

-

284

-

285

-

286

-

287

-

288

-

289

-

290

-

291

-

292

-

293

-

294

-

295

-

296

-

297

-

298

-

299

-

300

-

301

-

302

-

303

-

304

-

305

-

306

-

307

-

308

-

309

-

310

-

311

-

312

-

313

-

314

-

315

-

316

-

317

-

318

-

319

-

320

-

321

-

322

-

323

-

324

-

325

-

326

-

327

-

328

-

329

-

330

-

331

-

332

-

333

-

334

-

335

-

336

-

337

-

338

-

339

-

340

-

341

-

342

-

343

-

344

-

345

-

346

-

347

-

348

-

349

-

350

-

351

-

352

-

353

-

354

-

355

-

356

-

357

-

358

-

359

-

360

-

361

-

362

-

363

-

364

-

365

-

366

-

367

-

368

-

369

-

370

-

371

-

372

-

373

-

374

-

375

-

376

-

377

-

378

-

379

-

380

-

381

-

382

-

383

-

384

-

385

-

386

-

387

-

388

-

389

-

390

-

391

-

392

-

393

-

394

-

395

-

396

-

397

-

398

-

399

-

400

-

401

-

402

-

403

-

404

-

405

-

406

-

407

-

408

-

409

-

410

-

411

-

412

-

413

-

414

-

415

-

416

-

417

-

418

-

419

-

420

-

421

-

422

-

423

-

424

-

425

-

426

-

427

-

428

-

429

-

430

-

431

-

432

-

433

-

434

-

435

-

436

-

437

-

438

-

439

-

440

-

441

-

442

-

443

-

444

-

445

-

446

-

447

-

448

-

449

-

450

-

451

-

452

-

453

-

454

-

455

-

456

-

457

-

458

-

459

-

460

-

461

-

462

-

463

-

464

-

465

-

466

-

467

-

468

-

469

-

470

-

471

-

472

-

473

-

474

-

475

-

476

-

477

-

478

-

479

-

480

-

481

-

482

-

483

-

484

-

485

-

486

-

487

-

488

-

489

-

490

-

491

-

492

-

493

-

494

-

495

-

496

- -
-

""" 

-

Tools 

-

 

-

A module for converting from mpl language to plotly language. 

-

 

-

""" 

-

 

-

import math 

-

import warnings 

-

 

-

def check_bar_match(old_bar, new_bar): 

-

    """Check if two bars belong in the same collection (bar chart). 

-

 

-

    Positional arguments: 

-

    old_bar -- a previously sorted bar dictionary. 

-

    new_bar -- a new bar dictionary that needs to be sorted. 

-

 

-

    """ 

-

    tests = [] 

-

    tests += new_bar['orientation'] == old_bar['orientation'], 

-

    tests += new_bar['facecolor'] == old_bar['facecolor'], 

-

    if new_bar['orientation'] == 'v': 

-

        new_width = new_bar['x1'] - new_bar['x0'] 

-

        old_width = old_bar['x1'] - old_bar['x0'] 

-

        tests += new_width - old_width < 0.000001, 

-

        tests += new_bar['y0'] == old_bar['y0'], 

-

    elif new_bar['orientation'] == 'h': 

-

        new_height = new_bar['y1'] - new_bar['y0'] 

-

        old_height = old_bar['y1'] - old_bar['y0'] 

-

        tests += new_height - old_height < 0.000001, 

-

        tests += new_bar['x0'] == old_bar['x0'], 

-

    if all(tests): 

-

        return True 

-

    else: 

-

        return False 

-

 

-

 

-

def check_corners(inner_obj, outer_obj): 

-

    inner_corners = inner_obj.get_window_extent().corners() 

-

    outer_corners = outer_obj.get_window_extent().corners() 

-

    if inner_corners[0][0] < outer_corners[0][0]: 

-

        return False 

-

    elif inner_corners[0][1] < outer_corners[0][1]: 

-

        return False 

-

    elif inner_corners[3][0] > outer_corners[3][0]: 

-

        return False 

-

    elif inner_corners[3][1] > outer_corners[3][1]: 

-

        return False 

-

    else: 

-

        return True 

-

 

-

 

-

def convert_dash(mpl_dash): 

-

    """Convert mpl line symbol to plotly line symbol and return symbol.""" 

-

    if mpl_dash in DASH_MAP: 

-

        return DASH_MAP[mpl_dash] 

-

    else: 

-

        return 'solid'  # default 

-

 

-

 

-

def convert_path(path): 

-

    verts = path[0]  # may use this later 

-

    code = tuple(path[1]) 

-

    if code in PATH_MAP: 

-

        return PATH_MAP[code] 

-

    else: 

-

        return None 

-

 

-

 

-

def convert_symbol(mpl_symbol): 

-

    """Convert mpl marker symbol to plotly symbol and return symbol.""" 

-

    if isinstance(mpl_symbol, list): 

-

        symbol = list() 

-

        for s in mpl_symbol: 

-

            symbol += [convert_symbol(s)] 

-

        return symbol 

-

    elif mpl_symbol in SYMBOL_MAP: 

-

        return SYMBOL_MAP[mpl_symbol] 

-

    else: 

-

        return 'dot'  # default 

-

 

-

 

-

def convert_va(mpl_va): 

-

    """Convert mpl vertical alignment word to equivalent HTML word. 

-

 

-

    Text alignment specifiers from mpl differ very slightly from those used 

-

    in HTML. See the VA_MAP for more details. 

-

 

-

    Positional arguments: 

-

    mpl_va -- vertical mpl text alignment spec. 

-

 

-

    """ 

-

    if mpl_va in VA_MAP: 

-

        return VA_MAP[mpl_va] 

-

    else: 

-

        return None  # let plotly figure it out! 

-

 

-

 

-

def convert_x_domain(mpl_plot_bounds, mpl_max_x_bounds): 

-

    """Map x dimension of current plot to plotly's domain space. 

-

 

-

    The bbox used to locate an axes object in mpl differs from the 

-

    method used to locate axes in plotly. The mpl version locates each 

-

    axes in the figure so that axes in a single-plot figure might have 

-

    the bounds, [0.125, 0.125, 0.775, 0.775] (x0, y0, width, height), 

-

    in mpl's figure coordinates. However, the axes all share one space in 

-

    plotly such that the domain will always be [0, 0, 1, 1] 

-

    (x0, y0, x1, y1). To convert between the two, the mpl figure bounds 

-

    need to be mapped to a [0, 1] domain for x and y. The margins set 

-

    upon opening a new figure will appropriately match the mpl margins. 

-

 

-

    Optionally, setting margins=0 and simply copying the domains from 

-

    mpl to plotly would place axes appropriately. However, 

-

    this would throw off axis and title labeling. 

-

 

-

    Positional arguments: 

-

    mpl_plot_bounds -- the (x0, y0, width, height) params for current ax ** 

-

    mpl_max_x_bounds -- overall (x0, x1) bounds for all axes ** 

-

 

-

    ** these are all specified in mpl figure coordinates 

-

 

-

    """ 

-

    mpl_x_dom = [mpl_plot_bounds[0], mpl_plot_bounds[0]+mpl_plot_bounds[2]] 

-

    plotting_width = (mpl_max_x_bounds[1]-mpl_max_x_bounds[0]) 

-

    x0 = (mpl_x_dom[0]-mpl_max_x_bounds[0])/plotting_width 

-

    x1 = (mpl_x_dom[1]-mpl_max_x_bounds[0])/plotting_width 

-

    return [x0, x1] 

-

 

-

 

-

def convert_y_domain(mpl_plot_bounds, mpl_max_y_bounds): 

-

    """Map y dimension of current plot to plotly's domain space. 

-

 

-

    The bbox used to locate an axes object in mpl differs from the 

-

    method used to locate axes in plotly. The mpl version locates each 

-

    axes in the figure so that axes in a single-plot figure might have 

-

    the bounds, [0.125, 0.125, 0.775, 0.775] (x0, y0, width, height), 

-

    in mpl's figure coordinates. However, the axes all share one space in 

-

    plotly such that the domain will always be [0, 0, 1, 1] 

-

    (x0, y0, x1, y1). To convert between the two, the mpl figure bounds 

-

    need to be mapped to a [0, 1] domain for x and y. The margins set 

-

    upon opening a new figure will appropriately match the mpl margins. 

-

 

-

    Optionally, setting margins=0 and simply copying the domains from 

-

    mpl to plotly would place axes appropriately. However, 

-

    this would throw off axis and title labeling. 

-

 

-

    Positional arguments: 

-

    mpl_plot_bounds -- the (x0, y0, width, height) params for current ax ** 

-

    mpl_max_y_bounds -- overall (y0, y1) bounds for all axes ** 

-

 

-

    ** these are all specified in mpl figure coordinates 

-

 

-

    """ 

-

    mpl_y_dom = [mpl_plot_bounds[1], mpl_plot_bounds[1]+mpl_plot_bounds[3]] 

-

    plotting_height = (mpl_max_y_bounds[1]-mpl_max_y_bounds[0]) 

-

    y0 = (mpl_y_dom[0]-mpl_max_y_bounds[0])/plotting_height 

-

    y1 = (mpl_y_dom[1]-mpl_max_y_bounds[0])/plotting_height 

-

    return [y0, y1] 

-

 

-

 

-

def display_to_paper(x, y, layout): 

-

    """Convert mpl display coordinates to plotly paper coordinates. 

-

 

-

    Plotly references object positions with an (x, y) coordinate pair in either 

-

    'data' or 'paper' coordinates which reference actual data in a plot or 

-

    the entire plotly axes space where the bottom-left of the bottom-left 

-

    plot has the location (x, y) = (0, 0) and the top-right of the top-right 

-

    plot has the location (x, y) = (1, 1). Display coordinates in mpl reference 

-

    objects with an (x, y) pair in pixel coordinates, where the bottom-left 

-

    corner is at the location (x, y) = (0, 0) and the top-right corner is at 

-

    the location (x, y) = (figwidth*dpi, figheight*dpi). Here, figwidth and 

-

    figheight are in inches and dpi are the dots per inch resolution. 

-

 

-

    """ 

-

    num_x = x - layout['margin']['l'] 

-

    den_x = layout['width'] - (layout['margin']['l'] + layout['margin']['r']) 

-

    num_y = y - layout['margin']['b'] 

-

    den_y = layout['height'] - (layout['margin']['b'] + layout['margin']['t']) 

-

    return num_x/den_x, num_y/den_y 

-

 

-

 

-

def get_axes_bounds(fig): 

-

    """Return the entire axes space for figure. 

-

 

-

    An axes object in mpl is specified by its relation to the figure where 

-

    (0,0) corresponds to the bottom-left part of the figure and (1,1) 

-

    corresponds to the top-right. Margins exist in matplotlib because axes 

-

    objects normally don't go to the edges of the figure. 

-

 

-

    In plotly, the axes area (where all subplots go) is always specified with 

-

    the domain [0,1] for both x and y. This function finds the smallest box, 

-

    specified by two points, that all of the mpl axes objects fit into. This 

-

    box is then used to map mpl axes domains to plotly axes domains. 

-

 

-

    """ 

-

    x_min, x_max, y_min, y_max = [], [], [], [] 

-

    for axes_obj in fig.get_axes(): 

-

        bounds = axes_obj.get_position().bounds 

-

        x_min.append(bounds[0]) 

-

        x_max.append(bounds[0]+bounds[2]) 

-

        y_min.append(bounds[1]) 

-

        y_max.append(bounds[1]+bounds[3]) 

-

    x_min, y_min, x_max, y_max = min(x_min), min(y_min), max(x_max), max(y_max) 

-

    return (x_min, x_max), (y_min, y_max) 

-

 

-

 

-

def get_axis_mirror(main_spine, mirror_spine): 

-

    if main_spine and mirror_spine: 

-

        return 'ticks' 

-

    elif main_spine and not mirror_spine: 

-

        return False 

-

    elif not main_spine and mirror_spine: 

-

        return False  # can't handle this case yet! 

-

    else: 

-

        return False  # nuttin'! 

-

 

-

 

-

def get_bar_gap(bar_starts, bar_ends, tol=1e-10): 

-

    if len(bar_starts) == len(bar_ends) and len(bar_starts) > 1: 

-

        sides1 = bar_starts[1:] 

-

        sides2 = bar_ends[:-1] 

-

        gaps = [s2-s1 for s2, s1 in zip(sides1, sides2)] 

-

        gap0 = gaps[0] 

-

        uniform = all([abs(gap0-gap) < tol for gap in gaps]) 

-

        if uniform: 

-

            return gap0 

-

 

-

 

-

def convert_rgba_array(color_list): 

-

    clean_color_list = list() 

-

    for c in color_list: 

-

        clean_color_list += [(dict(r=int(c[0]*255), 

-

                                   g=int(c[1]*255), 

-

                                   b=int(c[2]*255), 

-

                                   a=c[3] 

-

        ))] 

-

    plotly_colors = list() 

-

    for rgba in clean_color_list: 

-

        plotly_colors += ["rgba({r},{g},{b},{a})".format(**rgba)] 

-

    if len(plotly_colors) == 1: 

-

        return plotly_colors[0] 

-

    else: 

-

        return plotly_colors 

-

 

-

 

-

def convert_path_array(path_array): 

-

    symbols = list() 

-

    for path in path_array: 

-

        symbols += [convert_path(path)] 

-

    if len(symbols) == 1: 

-

        return symbols[0] 

-

    else: 

-

        return symbols 

-

 

-

def convert_linewidth_array(width_array): 

-

    if len(width_array) == 1: 

-

        return width_array[0] 

-

    else: 

-

        return width_array 

-

 

-

 

-

def convert_size_array(size_array): 

-

    size = [math.sqrt(s) for s in size_array] 

-

    if len(size) == 1: 

-

        return size[0] 

-

    else: 

-

        return size 

-

 

-

 

-

def get_markerstyle_from_collection(props): 

-

    markerstyle=dict( 

-

        alpha=None, 

-

        facecolor=convert_rgba_array(props['styles']['facecolor']), 

-

        marker=convert_path_array(props['paths']), 

-

        edgewidth=convert_linewidth_array(props['styles']['linewidth']), 

-

        # markersize=convert_size_array(props['styles']['size']),  # TODO! 

-

        markersize=convert_size_array(props['mplobj'].get_sizes()), 

-

        edgecolor=convert_rgba_array(props['styles']['edgecolor']) 

-

    ) 

-

    return markerstyle 

-

 

-

 

-

def get_rect_xmin(data): 

-

    """Find minimum x value from four (x,y) vertices.""" 

-

    return min(data[0][0], data[1][0], data[2][0], data[3][0]) 

-

 

-

 

-

def get_rect_xmax(data): 

-

    """Find maximum x value from four (x,y) vertices.""" 

-

    return max(data[0][0], data[1][0], data[2][0], data[3][0]) 

-

 

-

 

-

def get_rect_ymin(data): 

-

    """Find minimum y value from four (x,y) vertices.""" 

-

    return min(data[0][1], data[1][1], data[2][1], data[3][1]) 

-

 

-

 

-

def get_rect_ymax(data): 

-

    """Find maximum y value from four (x,y) vertices.""" 

-

    return max(data[0][1], data[1][1], data[2][1], data[3][1]) 

-

 

-

def get_spine_visible(ax, spine_key): 

-

    """Return some spine parameters for the spine, `spine_key`.""" 

-

    spine = ax.spines[spine_key] 

-

    ax_frame_on = ax.get_frame_on() 

-

    spine_frame_like = spine.is_frame_like() 

-

    if not spine.get_visible(): 

-

        return False 

-

    elif not spine._edgecolor[-1]:  # user's may have set edgecolor alpha==0 

-

        return False 

-

    elif not ax_frame_on and spine_frame_like: 

-

        return False 

-

    elif ax_frame_on and spine_frame_like: 

-

        return True 

-

    elif not ax_frame_on and not spine_frame_like: 

-

        return True  # we've already checked for that it's visible. 

-

    else: 

-

        return False # oh man, and i thought we exhausted the options... 

-

 

-

 

-

def is_bar(**props): 

-

    """A test to decide whether a path is a bar from a vertical bar chart.""" 

-

    tests = [] 

-

    tests += get_rect_ymin(props['data']) == 0, 

-

    if all(tests): 

-

        return True 

-

    else: 

-

        return False 

-

 

-

 

-

def is_barh(**props): 

-

    """A test to decide whether a path is a bar from a horizontal bar chart.""" 

-

    tests = [] 

-

    tests += get_rect_xmin(props['data']) == 0, 

-

    if all(tests): 

-

        return True 

-

    else: 

-

        return False 

-

 

-

 

-

def make_bar(**props): 

-

    """Make an intermediate bar dictionary. 

-

 

-

    This creates a bar dictionary which aids in the comparison of new bars to 

-

    old bars from other bar chart (patch) collections. This is not the 

-

    dictionary that needs to get passed to plotly as a data dictionary. That 

-

    happens in PlotlyRenderer in that class's draw_bar method. In other 

-

    words, this dictionary describes a SINGLE bar, whereas, plotly will 

-

    require a set of bars to be passed in a data dictionary. 

-

 

-

    """ 

-

    return { 

-

        'bar': props['mplobj'], 

-

        'orientation': props['orientation'], 

-

        'x0': get_rect_xmin(props['data']), 

-

        'y0': get_rect_ymin(props['data']), 

-

        'x1': get_rect_xmax(props['data']), 

-

        'y1': get_rect_ymax(props['data']), 

-

        'alpha': props['style']['alpha'], 

-

        'edgecolor': props['style']['edgecolor'], 

-

        'facecolor': props['style']['facecolor'], 

-

        'edgewidth': props['style']['edgewidth'], 

-

        'dasharray': props['style']['dasharray'], 

-

        'zorder': props['style']['zorder'] 

-

    } 

-

 

-

def prep_ticks(ax, index, ax_type, props): 

-

    """Prepare axis obj belonging to axes obj. 

-

 

-

    positional arguments: 

-

    ax - the mpl axes instance 

-

    index - the index of the axis in `props` 

-

    ax_type - 'x' or 'y' (for now) 

-

    props - an mplexporter poperties dictionary 

-

 

-

    """ 

-

    axis_dict = dict() 

-

    if ax_type == 'x': 

-

        axis = ax.get_xaxis() 

-

    elif ax_type == 'y': 

-

        axis = ax.get_yaxis() 

-

    else: 

-

        return dict() # whoops! 

-

 

-

    scale = props['axes'][index]['scale'] 

-

    if scale == 'linear': 

-

        # get tick location information 

-

        try: 

-

            tickvalues = props['axes'][index]['tickvalues'] 

-

            tick0 = tickvalues[0] 

-

            dticks = [round(tickvalues[i]-tickvalues[i-1], 12) 

-

                      for i in range(1, len(tickvalues) - 1)] 

-

            if all([dticks[i] == dticks[i-1] 

-

                    for i in range(1, len(dticks) - 1)]): 

-

                dtick = tickvalues[1] - tickvalues[0] 

-

            else: 

-

                warnings.warn("'linear' {}-axis tick spacing not even, " 

-

                              "ignoring mpl tick formatting.".format(ax_type)) 

-

                raise TypeError 

-

        except (IndexError, TypeError): 

-

            axis_dict['nticks'] = props['axes'][index]['nticks'] 

-

        else: 

-

            axis_dict['tick0'] = tick0 

-

            axis_dict['dtick'] = dtick 

-

            axis_dict['autotick'] = False 

-

    elif scale == 'log': 

-

        try: 

-

            axis_dict['tick0'] = props['axes'][index]['tickvalues'][0] 

-

            axis_dict['dtick'] = props['axes'][index]['tickvalues'][1] - \ 

-

                            props['axes'][index]['tickvalues'][0] 

-

            axis_dict['autotick'] = False 

-

        except (IndexError, TypeError): 

-

            axis_dict = dict(nticks=props['axes'][index]['nticks']) 

-

        base = axis.get_transform().base 

-

        if base == 10: 

-

            if ax_type == 'x': 

-

                axis_dict['range'] = [math.log10(props['xlim'][0]), 

-

                                 math.log10(props['xlim'][1])] 

-

            elif ax_type == 'y': 

-

                axis_dict['range'] = [math.log10(props['ylim'][0]), 

-

                                 math.log10(props['ylim'][1])] 

-

        else: 

-

            axis_dict = dict(range=None, type='linear') 

-

            warnings.warn("Converted non-base10 {}-axis log scale to 'linear'" 

-

                          "".format(ax_type)) 

-

    else: 

-

        return dict() 

-

    # get tick label formatting information 

-

    formatter = axis.get_major_formatter().__class__.__name__ 

-

    if formatter == 'LogFormatterMathtext': 

-

        axis_dict['exponentformat'] = 'e' 

-

    return axis_dict 

-

 

-

 

-

def prep_xy_axis(ax, props, x_bounds, y_bounds): 

-

    xaxis = dict( 

-

        type=props['axes'][0]['scale'], 

-

        range=list(props['xlim']), 

-

        showgrid=props['axes'][0]['grid']['gridOn'], 

-

        domain=convert_x_domain(props['bounds'], x_bounds), 

-

        side=props['axes'][0]['position'], 

-

        tickfont=dict(size=props['axes'][0]['fontsize']) 

-

    ) 

-

    xaxis.update(prep_ticks(ax, 0, 'x', props)) 

-

    yaxis = dict( 

-

        type=props['axes'][1]['scale'], 

-

        range=list(props['ylim']), 

-

        showgrid=props['axes'][1]['grid']['gridOn'], 

-

        domain=convert_y_domain(props['bounds'], y_bounds), 

-

        side=props['axes'][1]['position'], 

-

        tickfont=dict(size=props['axes'][1]['fontsize']) 

-

    ) 

-

    yaxis.update(prep_ticks(ax, 1, 'y', props)) 

-

    return xaxis, yaxis 

-

 

-

 

-

DASH_MAP = { 

-

    '10,0': 'solid', 

-

    '6,6': 'dash', 

-

    '2,2': 'dot', 

-

    '4,4,2,4': 'dashdot', 

-

    'none': 'solid' 

-

} 

-

 

-

PATH_MAP = { 

-

    ('M', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'Z'): 'o', 

-

    ('M', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'Z'): '*', 

-

    ('M', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'Z'): '8', 

-

    ('M', 'L', 'L', 'L', 'L', 'L', 'Z'): 'h', 

-

    ('M', 'L', 'L', 'L', 'L', 'Z'): 'p', 

-

    ('M', 'L', 'M', 'L', 'M', 'L'): '1', 

-

    ('M', 'L', 'L', 'L', 'Z'): 's', 

-

    ('M', 'L', 'M', 'L'): '+', 

-

    ('M', 'L', 'L', 'Z'): '^', 

-

    ('M', 'L'): '|' 

-

} 

-

 

-

SYMBOL_MAP = { 

-

    'o': 'dot', 

-

    'v': 'triangle-down', 

-

    '^': 'triangle-up', 

-

    '<': 'triangle-left', 

-

    '>': 'triangle-right', 

-

    's': 'square', 

-

    '+': 'cross', 

-

    'x': 'x', 

-

    '*': 'x',  # no star yet in plotly!! 

-

    'D': 'diamond', 

-

    'd': 'diamond', 

-

} 

-

 

-

VA_MAP = { 

-

    'center': 'middle', 

-

    'baseline': 'bottom', 

-

    'top': 'top' 

-

} 

- -
-
- - - - - diff --git a/plotly/tests/coverage/plotly_matplotlylib_renderer.html b/plotly/tests/coverage/plotly_matplotlylib_renderer.html deleted file mode 100644 index e3a4765ec65..00000000000 --- a/plotly/tests/coverage/plotly_matplotlylib_renderer.html +++ /dev/null @@ -1,1490 +0,0 @@ - - - - - - - - Coverage for plotly/matplotlylib/renderer: 73% - - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

-

27

-

28

-

29

-

30

-

31

-

32

-

33

-

34

-

35

-

36

-

37

-

38

-

39

-

40

-

41

-

42

-

43

-

44

-

45

-

46

-

47

-

48

-

49

-

50

-

51

-

52

-

53

-

54

-

55

-

56

-

57

-

58

-

59

-

60

-

61

-

62

-

63

-

64

-

65

-

66

-

67

-

68

-

69

-

70

-

71

-

72

-

73

-

74

-

75

-

76

-

77

-

78

-

79

-

80

-

81

-

82

-

83

-

84

-

85

-

86

-

87

-

88

-

89

-

90

-

91

-

92

-

93

-

94

-

95

-

96

-

97

-

98

-

99

-

100

-

101

-

102

-

103

-

104

-

105

-

106

-

107

-

108

-

109

-

110

-

111

-

112

-

113

-

114

-

115

-

116

-

117

-

118

-

119

-

120

-

121

-

122

-

123

-

124

-

125

-

126

-

127

-

128

-

129

-

130

-

131

-

132

-

133

-

134

-

135

-

136

-

137

-

138

-

139

-

140

-

141

-

142

-

143

-

144

-

145

-

146

-

147

-

148

-

149

-

150

-

151

-

152

-

153

-

154

-

155

-

156

-

157

-

158

-

159

-

160

-

161

-

162

-

163

-

164

-

165

-

166

-

167

-

168

-

169

-

170

-

171

-

172

-

173

-

174

-

175

-

176

-

177

-

178

-

179

-

180

-

181

-

182

-

183

-

184

-

185

-

186

-

187

-

188

-

189

-

190

-

191

-

192

-

193

-

194

-

195

-

196

-

197

-

198

-

199

-

200

-

201

-

202

-

203

-

204

-

205

-

206

-

207

-

208

-

209

-

210

-

211

-

212

-

213

-

214

-

215

-

216

-

217

-

218

-

219

-

220

-

221

-

222

-

223

-

224

-

225

-

226

-

227

-

228

-

229

-

230

-

231

-

232

-

233

-

234

-

235

-

236

-

237

-

238

-

239

-

240

-

241

-

242

-

243

-

244

-

245

-

246

-

247

-

248

-

249

-

250

-

251

-

252

-

253

-

254

-

255

-

256

-

257

-

258

-

259

-

260

-

261

-

262

-

263

-

264

-

265

-

266

-

267

-

268

-

269

-

270

-

271

-

272

-

273

-

274

-

275

-

276

-

277

-

278

-

279

-

280

-

281

-

282

-

283

-

284

-

285

-

286

-

287

-

288

-

289

-

290

-

291

-

292

-

293

-

294

-

295

-

296

-

297

-

298

-

299

-

300

-

301

-

302

-

303

-

304

-

305

-

306

-

307

-

308

-

309

-

310

-

311

-

312

-

313

-

314

-

315

-

316

-

317

-

318

-

319

-

320

-

321

-

322

-

323

-

324

-

325

-

326

-

327

-

328

-

329

-

330

-

331

-

332

-

333

-

334

-

335

-

336

-

337

-

338

-

339

-

340

-

341

-

342

-

343

-

344

-

345

-

346

-

347

-

348

-

349

-

350

-

351

-

352

-

353

-

354

-

355

-

356

-

357

-

358

-

359

-

360

-

361

-

362

-

363

-

364

-

365

-

366

-

367

-

368

-

369

-

370

-

371

-

372

-

373

-

374

-

375

-

376

-

377

-

378

-

379

-

380

-

381

-

382

-

383

-

384

-

385

-

386

-

387

-

388

-

389

-

390

-

391

-

392

-

393

-

394

-

395

-

396

-

397

-

398

-

399

-

400

-

401

-

402

-

403

-

404

-

405

-

406

-

407

-

408

-

409

-

410

-

411

-

412

-

413

-

414

-

415

-

416

-

417

-

418

-

419

-

420

-

421

-

422

-

423

-

424

-

425

-

426

-

427

-

428

-

429

-

430

-

431

-

432

-

433

-

434

-

435

-

436

-

437

-

438

-

439

-

440

-

441

-

442

-

443

-

444

-

445

-

446

-

447

-

448

-

449

-

450

-

451

-

452

-

453

-

454

-

455

-

456

-

457

-

458

-

459

-

460

-

461

-

462

-

463

-

464

-

465

-

466

-

467

-

468

-

469

-

470

-

471

-

472

-

473

-

474

-

475

-

476

-

477

-

478

-

479

-

480

-

481

-

482

-

483

-

484

-

485

-

486

-

487

-

488

-

489

-

490

-

491

-

492

-

493

-

494

-

495

-

496

-

497

-

498

-

499

-

500

-

501

-

502

-

503

-

504

-

505

-

506

-

507

-

508

-

509

-

510

-

511

-

512

-

513

-

514

-

515

-

516

-

517

-

518

-

519

-

520

-

521

-

522

-

523

-

524

-

525

-

526

-

527

-

528

-

529

-

530

-

531

-

532

-

533

-

534

-

535

-

536

-

537

-

538

-

539

-

540

-

541

-

542

-

543

-

544

-

545

-

546

-

547

-

548

-

549

-

550

-

551

-

552

-

553

-

554

-

555

-

556

-

557

-

558

-

559

-

560

-

561

-

562

-

563

-

564

-

565

-

566

-

567

-

568

-

569

-

570

-

571

-

572

-

573

-

574

-

575

-

576

-

577

-

578

-

579

-

580

-

581

-

582

-

583

-

584

-

585

-

586

-

587

-

588

-

589

-

590

-

591

-

592

-

593

-

594

-

595

-

596

-

597

-

598

-

599

-

600

-

601

-

602

-

603

-

604

-

605

-

606

-

607

-

608

-

609

-

610

-

611

-

612

-

613

-

614

-

615

-

616

-

617

-

618

-

619

-

620

-

621

-

622

-

623

-

624

-

625

-

626

-

627

-

628

-

629

-

630

-

631

-

632

-

633

-

634

-

635

-

636

-

637

-

638

-

639

-

640

-

641

-

642

-

643

-

644

-

645

-

646

-

647

-

648

-

649

-

650

-

651

-

652

-

653

-

654

-

655

-

656

-

657

-

658

-

659

-

660

-

661

-

662

-

663

-

664

-

665

-

666

-

667

-

668

-

669

-

670

-

671

-

672

-

673

-

674

-

675

-

676

-

677

-

678

-

679

-

680

-

681

-

682

-

683

-

684

-

685

-

686

-

687

-

688

-

689

-

690

-

691

-

692

-

693

-

694

-

695

-

696

-

697

-

698

-

699

-

700

-

701

-

702

-

703

-

704

- -
-

""" 

-

Renderer Module 

-

 

-

This module defines the PlotlyRenderer class and a single function, 

-

fig_to_plotly, which is intended to be the main way that user's will interact 

-

with the matplotlylib package. 

-

 

-

""" 

-

from __future__ import absolute_import 

-

 

-

import warnings 

-

 

-

from . mplexporter import Renderer 

-

from . import mpltools 

-

from plotly.graph_objs import * 

-

 

-

 

-

 

-

# Warning format 

-

def warning_on_one_line(message, category, filename, lineno, file=None, line=None): 

-

    return '%s:%s: %s:\n\n%s\n\n' % (filename, lineno, category.__name__, message) 

-

warnings.formatwarning = warning_on_one_line 

-

 

-

class PlotlyRenderer(Renderer): 

-

    """A renderer class inheriting from base for rendering mpl plots in plotly. 

-

 

-

    A renderer class to be used with an exporter for rendering matplotlib 

-

    plots in Plotly. This module defines the PlotlyRenderer class which handles 

-

    the creation of the JSON structures that get sent to plotly. 

-

 

-

    All class attributes available are defined in __init__(). 

-

 

-

    Basic Usage: 

-

 

-

    # (mpl code) # 

-

    fig = gcf() 

-

    renderer = PlotlyRenderer(fig) 

-

    exporter = Exporter(renderer) 

-

    exporter.run(fig)  # ... et voila 

-

 

-

    """ 

-

    def __init__(self): 

-

        """Initialize PlotlyRenderer obj. 

-

 

-

        PlotlyRenderer obj is called on by an Exporter object to draw 

-

        matplotlib objects like figures, axes, text, etc. 

-

 

-

        All class attributes are listed here in the __init__ method. 

-

 

-

        """ 

-

        self.plotly_fig = Figure(data=Data(), layout=Layout()) 

-

        self.mpl_fig = None 

-

        self.current_ax_patches = [] 

-

        self.axis_ct = 0 

-

        self.mpl_x_bounds = (0, 1) 

-

        self.mpl_y_bounds = (0, 1) 

-

        self.msg = "Initialized PlotlyRenderer\n" 

-

 

-

    def open_figure(self, fig, props): 

-

        """Creates a new figure by beginning to fill out layout dict. 

-

 

-

        The 'autosize' key is set to false so that the figure will mirror 

-

        sizes set by mpl. The 'hovermode' key controls what shows up when you 

-

        mouse around a figure in plotly, it's set to show the 'closest' point. 

-

 

-

        Positional agurments: 

-

        fig -- a matplotlib.figure.Figure object. 

-

        props.keys(): [ 

-

            'figwidth', 

-

            'figheight', 

-

            'dpi' 

-

            ] 

-

 

-

        """ 

-

        self.msg += "Opening figure\n" 

-

        self.mpl_fig = fig 

-

        self.plotly_fig['layout'] = Layout( 

-

            width=int(props['figwidth']*props['dpi']), 

-

            height=int(props['figheight']*props['dpi']), 

-

            autosize=False, 

-

            hovermode='closest') 

-

        self.mpl_x_bounds, self.mpl_y_bounds = mpltools.get_axes_bounds(fig) 

-

        margin = Margin( 

-

            l=int(self.mpl_x_bounds[0]*self.plotly_fig['layout']['width']), 

-

            r=int((1-self.mpl_x_bounds[1])*self.plotly_fig['layout']['width']), 

-

            t=int((1-self.mpl_y_bounds[1])*self.plotly_fig['layout']['height']), 

-

            b=int(self.mpl_y_bounds[0]*self.plotly_fig['layout']['height']), 

-

            pad=0) 

-

        self.plotly_fig['layout']['margin'] = margin 

-

 

-

    def close_figure(self, fig): 

-

        """Closes figure by cleaning up data and layout dictionaries. 

-

 

-

        The PlotlyRenderer's job is to create an appropriate set of data and 

-

        layout dictionaries. When the figure is closed, some cleanup and 

-

        repair is necessary. This method removes inappropriate dictionary 

-

        entries, freeing up Plotly to use defaults and best judgements to 

-

        complete the entries. This method is called by an Exporter object. 

-

 

-

        Positional arguments: 

-

        fig -- a matplotlib.figure.Figure object. 

-

 

-

        """ 

-

        self.plotly_fig.force_clean() 

-

        self.plotly_fig['layout']['showlegend'] = False 

-

        self.msg += "Closing figure\n" 

-

 

-

    def open_axes(self, ax, props): 

-

        """Setup a new axes object (subplot in plotly). 

-

 

-

        Plotly stores information about subplots in different 'xaxis' and 

-

        'yaxis' objects which are numbered. These are just dictionaries 

-

        included in the layout dictionary. This function takes information 

-

        from the Exporter, fills in appropriate dictionary entries, 

-

        and updates the layout dictionary. PlotlyRenderer keeps track of the 

-

        number of plots by incrementing the axis_ct attribute. 

-

 

-

        Setting the proper plot domain in plotly is a bit tricky. Refer to 

-

        the documentation for mpltools.convert_x_domain and 

-

        mpltools.convert_y_domain. 

-

 

-

        Positional arguments: 

-

        ax -- an mpl axes object. This will become a subplot in plotly. 

-

        props.keys() -- [ 

-

            'axesbg',           (background color for axes obj) 

-

            'axesbgalpha',      (alpha, or opacity for background) 

-

            'bounds',           ((x0, y0, width, height) for axes) 

-

            'dynamic',          (zoom/pan-able?) 

-

            'axes',             (list: [xaxis, yaxis]) 

-

            'xscale',           (log, linear, or date) 

-

            'yscale', 

-

            'xlim',             (range limits for x) 

-

            'ylim', 

-

            'xdomain'           (xdomain=xlim, unless it's a date) 

-

            'ydomain' 

-

            ] 

-

 

-

        """ 

-

        self.msg += "  Opening axes\n" 

-

        self.axis_ct += 1 

-

        # set defaults in axes 

-

        xaxis = XAxis( 

-

            anchor='y{0}'.format(self.axis_ct), 

-

            zeroline=False, 

-

            ticks='inside') 

-

        yaxis = YAxis( 

-

            anchor='x{0}'.format(self.axis_ct), 

-

            zeroline=False, 

-

            ticks='inside') 

-

        # update defaults with things set in mpl 

-

        mpl_xaxis, mpl_yaxis = mpltools.prep_xy_axis(ax=ax, 

-

                                                     props=props, 

-

                                                     x_bounds=self.mpl_x_bounds, 

-

                                                     y_bounds=self.mpl_y_bounds) 

-

        xaxis.update(mpl_xaxis) 

-

        yaxis.update(mpl_yaxis) 

-

        bottom_spine = mpltools.get_spine_visible(ax, 'bottom') 

-

        top_spine = mpltools.get_spine_visible(ax, 'top') 

-

        left_spine = mpltools.get_spine_visible(ax, 'left') 

-

        right_spine = mpltools.get_spine_visible(ax, 'right') 

-

        xaxis['mirror'] = mpltools.get_axis_mirror(bottom_spine, top_spine) 

-

        yaxis['mirror'] = mpltools.get_axis_mirror(left_spine, right_spine) 

-

        xaxis['showline'] = bottom_spine 

-

        yaxis['showline'] = top_spine 

-

 

-

 

-

        # put axes in our figure 

-

        self.plotly_fig['layout']['xaxis{0}'.format(self.axis_ct)] = xaxis 

-

        self.plotly_fig['layout']['yaxis{0}'.format(self.axis_ct)] = yaxis 

-

 

-

    def close_axes(self, ax): 

-

        """Close the axes object and clean up. 

-

 

-

        Bars from bar charts are given to PlotlyRenderer one-by-one, 

-

        thus they need to be taken care of at the close of each axes object. 

-

        The self.current_ax_patches variable should be empty unless a bar 

-

        chart has been created or a rectangle object has been drawn that has 

-

        an edge exactly on the lines x=0 or y=0. 

-

 

-

        Positional arguments: 

-

        ax -- an mpl axes object, not required at this time. 

-

 

-

        """ 

-

        for patch_coll in self.current_ax_patches: 

-

            self.draw_bar(patch_coll) 

-

        self.current_ax_patches = []  # clear this for next axes obj 

-

        self.msg += "  Closing axes\n" 

-

 

-

    def draw_bar(self, patch_coll): 

-

        """Draw a collection of similar patches as a bar chart. 

-

 

-

        After bars are sorted, an appropriate data dictionary must be created 

-

        to tell plotly about this data. Just like draw_line or draw_markers, 

-

        draw_bar translates patch/path information into something plotly 

-

        understands. 

-

 

-

        Positional arguments: 

-

        patch_coll -- a collection of patches to be drawn as a bar chart. 

-

 

-

        """ 

-

        orientation = patch_coll[0]['orientation'] 

-

        if orientation == 'v': 

-

            self.msg += "    Attempting to draw a vertical bar chart\n" 

-

            patch_coll.sort(key=lambda b: b['x0']) 

-

            x = [bar['x0']+(bar['x1']-bar['x0'])/2 for bar in patch_coll] 

-

            y = [bar['y1'] for bar in patch_coll] 

-

            bar_gap = mpltools.get_bar_gap([bar['x0'] for bar in patch_coll], 

-

                                           [bar['x1'] for bar in patch_coll]) 

-

        else: 

-

            self.msg += "    Attempting to draw a horizontal bar chart\n" 

-

            patch_coll.sort(key=lambda b: b['y0']) 

-

            x = [bar['x1'] for bar in patch_coll] 

-

            y = [bar['y0']+(bar['y1']-bar['y0'])/2 for bar in patch_coll] 

-

            bar_gap = mpltools.get_bar_gap([bar['y0'] for bar in patch_coll], 

-

                                           [bar['y1'] for bar in patch_coll]) 

-

        bar = Bar(orientation=orientation, 

-

                  x=x, 

-

                  y=y, 

-

                  xaxis='x{0}'.format(self.axis_ct), 

-

                  yaxis='y{0}'.format(self.axis_ct), 

-

                  opacity=patch_coll[0]['alpha'], 

-

                  marker=Marker( 

-

                      color=patch_coll[0]['facecolor'], 

-

                      line=Line(width=patch_coll[0]['edgewidth']))) 

-

        if len(bar['x']) > 1: 

-

            self.msg += "    Heck yeah, I drew that bar chart\n" 

-

            self.plotly_fig['data'] += bar, 

-

            if bar_gap is not None: 

-

                self.plotly_fig['layout']['bargap'] = bar_gap 

-

        else: 

-

            self.msg += "    Bar chart not drawn\n" 

-

            warnings.warn('found box chart data with length <= 1, ' 

-

                          'assuming data redundancy, not plotting.') 

-

 

-

    def draw_marked_line(self, **props): 

-

        """Create a data dict for a line obj. 

-

 

-

        This will draw 'lines', 'markers', or 'lines+markers'. 

-

 

-

        props.keys() -- [ 

-

        'coordinates',  ('data', 'axes', 'figure', or 'display') 

-

        'data',         (a list of xy pairs) 

-

        'mplobj',       (the matplotlib.lines.Line2D obj being rendered) 

-

        'label',        (the name of the Line2D obj being rendered) 

-

        'linestyle',    (linestyle dict, can be None, see below) 

-

        'markerstyle',  (markerstyle dict, can be None, see below) 

-

        ] 

-

 

-

        props['linestyle'].keys() -- [ 

-

        'alpha',        (opacity of Line2D obj) 

-

        'color',        (color of the line if it exists, not the marker) 

-

        'linewidth', 

-

        'dasharray',    (code for linestyle, see DASH_MAP in mpltools.py) 

-

        'zorder',       (viewing precedence when stacked with other objects) 

-

        ] 

-

 

-

        props['markerstyle'].keys() -- [ 

-

        'alpha',        (opacity of Line2D obj) 

-

        'marker',       (the mpl marker symbol, see SYMBOL_MAP in mpltools.py) 

-

        'facecolor',    (color of the marker face) 

-

        'edgecolor',    (color of the marker edge) 

-

        'edgewidth',    (width of marker edge) 

-

        'markerpath',   (an SVG path for drawing the specified marker) 

-

        'zorder',       (viewing precedence when stacked with other objects) 

-

        ] 

-

 

-

        """ 

-

        self.msg += "    Attempting to draw a line " 

-

        line, marker = {}, {} 

-

        if props['linestyle'] and props['markerstyle']: 

-

            self.msg += "... with both lines+markers\n" 

-

            mode = "lines+markers" 

-

        elif props['linestyle']: 

-

            self.msg += "... with just lines\n" 

-

            mode = "lines" 

-

        elif props['markerstyle']: 

-

            self.msg += "... with just markers\n" 

-

            mode = "markers" 

-

        if props['linestyle']: 

-

            line = Line( 

-

                opacity=props['linestyle']['alpha'], 

-

                color=props['linestyle']['color'], 

-

                width=props['linestyle']['linewidth'], 

-

                dash=mpltools.convert_dash(props['linestyle']['dasharray']) 

-

            ) 

-

        if props['markerstyle']: 

-

            marker = Marker( 

-

                opacity=props['markerstyle']['alpha'], 

-

                color=props['markerstyle']['facecolor'], 

-

                symbol=mpltools.convert_symbol(props['markerstyle']['marker']), 

-

                size=props['markerstyle']['markersize'], 

-

                line=Line( 

-

                    color=props['markerstyle']['edgecolor'], 

-

                    width=props['markerstyle']['edgewidth'] 

-

                ) 

-

            ) 

-

        if props['coordinates'] == 'data': 

-

            marked_line = Scatter(mode=mode, 

-

                                  name=props['label'], 

-

                                  x=[xy_pair[0] for xy_pair in props['data']], 

-

                                  y=[xy_pair[1] for xy_pair in props['data']], 

-

                                  xaxis='x{0}'.format(self.axis_ct), 

-

                                  yaxis='y{0}'.format(self.axis_ct), 

-

                                  line=line, 

-

                                  marker=marker) 

-

            self.plotly_fig['data'] += marked_line, 

-

            self.msg += "    Heck yeah, I drew that line\n" 

-

        else: 

-

            self.msg += "    Line didn't have 'data' coordinates, " \ 

-

                        "not drawing\n" 

-

            warnings.warn("Bummer! Plotly can currently only draw Line2D " 

-

                          "objects from matplotlib that are in 'data' " 

-

                          "coordinates!") 

-

 

-

    def draw_image(self, **props): 

-

        """Draw image. 

-

 

-

        Not implemented yet! 

-

 

-

        """ 

-

        self.msg += "    Attempting to draw image\n" 

-

        self.msg += "    Not drawing image\n" 

-

        warnings.warn("Aw. Snap! You're gonna have to hold off on " 

-

                      "the selfies for now. Plotly can't import " 

-

                      "images from matplotlib yet!") 

-

 

-

    def draw_path_collection(self, **props): 

-

        """Add a path collection to data list as a scatter plot. 

-

 

-

        Current implementation defaults such collections as scatter plots. 

-

        Matplotlib supports collections that have many of the same parameters 

-

        in common like color, size, path, etc. However, they needn't all be 

-

        the same. Plotly does not currently support such functionality and 

-

        therefore, the style for the first object is taken and used to define 

-

        the remaining paths in the collection. 

-

 

-

        props.keys() -- [ 

-

        'paths',                (structure: [vertices, path_code]) 

-

        'path_coordinates',     ('data', 'axes', 'figure', or 'display') 

-

        'path_transforms',      (mpl transform, including Affine2D matrix) 

-

        'offsets',              (offset from axes, helpful if in 'data') 

-

        'offset_coordinates',   ('data', 'axes', 'figure', or 'display') 

-

        'offset_order', 

-

        'styles',               (style dict, see below) 

-

        'mplobj'                (the collection obj being drawn) 

-

        ] 

-

 

-

        props['styles'].keys() -- [ 

-

        'linewidth',            (one or more linewidths) 

-

        'facecolor',            (one or more facecolors for path) 

-

        'edgecolor',            (one or more edgecolors for path) 

-

        'alpha',                (one or more opacites for path) 

-

        'zorder',               (precedence when stacked) 

-

        ] 

-

 

-

        """ 

-

        self.msg += "    Attempting to draw a path collection\n" 

-

        if props['offset_coordinates'] is 'data': 

-

            markerstyle = mpltools.get_markerstyle_from_collection(props) 

-

            scatter_props = { 

-

                'coordinates': 'data', 

-

                'data': props['offsets'], 

-

                'label': None, 

-

                'markerstyle': markerstyle, 

-

                'linestyle': None 

-

            } 

-

            self.msg += "    Drawing path collection as markers\n" 

-

            self.draw_marked_line(**scatter_props) 

-

        else: 

-

            self.msg += "    Path collection not linked to 'data', " \ 

-

                        "not drawing\n" 

-

            warnings.warn("Dang! That path collection is out of this " 

-

                          "world. I totally don't know what to do with " 

-

                          "it yet! Plotly can only import path " 

-

                          "collections linked to 'data' coordinates") 

-

 

-

    def draw_path(self, **props): 

-

        """Draw path, currently only attempts to draw bar charts. 

-

 

-

        This function attempts to sort a given path into a collection of 

-

        horizontal or vertical bar charts. Most of the actual code takes 

-

        place in functions from mpltools.py. 

-

 

-

        props.keys() -- [ 

-

        'data',         (a list of verticies for the path) 

-

        'coordinates',  ('data', 'axes', 'figure', or 'display') 

-

        'pathcodes',    (code for the path, structure: ['M', 'L', 'Z', etc.]) 

-

        'style',        (style dict, see below) 

-

        'mplobj'        (the mpl path object) 

-

        ] 

-

 

-

        props['style'].keys() -- [ 

-

        'alpha',        (opacity of path obj) 

-

        'edgecolor', 

-

        'facecolor', 

-

        'edgewidth', 

-

        'dasharray',    (style for path's enclosing line) 

-

        'zorder'        (precedence of obj when stacked) 

-

        ] 

-

 

-

        """ 

-

        self.msg += "    Attempting to draw a path\n" 

-

        is_bar = mpltools.is_bar(**props) 

-

        is_barh = mpltools.is_barh(**props) 

-

        if is_bar:  # if we think it's a bar, add it! 

-

            self.msg += "      Assuming path is a vertical bar\n" 

-

            bar = mpltools.make_bar(orientation='v', **props) 

-

            self.file_bar(bar) 

-

        if is_barh:  # perhaps a horizontal bar? 

-

            self.msg += "      Assuming path is a horizontal bar\n" 

-

            bar = mpltools.make_bar(orientation='h', **props) 

-

            self.file_bar(bar) 

-

        if not (is_bar or is_barh): 

-

            self.msg += "    This path isn't a bar, not drawing\n" 

-

            warnings.warn("I found a path object that I don't think is part " 

-

                          "of a bar chart. Ignoring.") 

-

 

-

    def file_bar(self, bar): 

-

        """Puts a given bar into an appropriate bar or barh collection. 

-

 

-

        Bars come from the mplexporter one-by-one. To try to put them into 

-

        appropriate data sets, we must compare them to existing data. 

-

 

-

        Positional arguments: 

-

        bar -- a bar dictionary created in mpltools.make_bar.py. 

-

 

-

        bar.keys() -- [ 

-

        'bar',          (mpl path object) 

-

        'orientation',  (bar direction, 'v' or 'h' for horizontal or vertical) 

-

        'x0',           ([x0, y0] = bottom-left corner of rectangle) 

-

        'y0', 

-

        'x1',           ([x1, y1] = top-right corner of rectangle): 

-

        'y1', 

-

        'alpha',        (opacity of rectangle) 

-

        'edgecolor',    (boundary line color) 

-

        'facecolor',    (rectangle color) 

-

        'edgewidth',    (boundary line width) 

-

        'dasharray',    (linestyle for boundary line) 

-

        'zorder',       (precedence when stacked) 

-

        ] 

-

 

-

        """ 

-

        self.msg += "        Putting a bar into the proper bar collection\n" 

-

        if len(self.current_ax_patches) == 0: 

-

            self.msg += "          Started a new bar collection with this " \ 

-

                        "bar\n" 

-

            self.current_ax_patches.append([]) 

-

            self.current_ax_patches[-1] += bar, 

-

        else: 

-

            match = False 

-

            for patch_collection in self.current_ax_patches: 

-

                if mpltools.check_bar_match(patch_collection[0], bar): 

-

                    match = True 

-

                    patch_collection += bar, 

-

                    self.msg += "          Filed bar into existing bar " \ 

-

                                "collection\n" 

-

            if not match: 

-

                self.msg += "          Started a new bar collection with " \ 

-

                            "this bar\n" 

-

                self.current_ax_patches.append([]) 

-

                self.current_ax_patches[-1] += bar, 

-

 

-

    def draw_text(self, **props): 

-

        """Create an annotation dict for a text obj. 

-

 

-

        Currently, plotly uses either 'page' or 'data' to reference 

-

        annotation locations. These refer to 'display' and 'data', 

-

        respectively for the 'coordinates' key used in the Exporter. 

-

        Appropriate measures are taken to transform text locations to 

-

        reference one of these two options. 

-

 

-

        props.keys() -- [ 

-

        'text',         (actual content string, not the text obj) 

-

        'position',     (an x, y pair, not an mpl Bbox) 

-

        'coordinates',  ('data', 'axes', 'figure', 'display') 

-

        'text_type',    ('title', 'xlabel', or 'ylabel') 

-

        'style',        (style dict, see below) 

-

        'mplobj'        (actual mpl text object) 

-

        ] 

-

 

-

        props['style'].keys() -- [ 

-

        'alpha',        (opacity of text) 

-

        'fontsize',     (size in points of text) 

-

        'color',        (hex color) 

-

        'halign',       (horizontal alignment, 'left', 'center', or 'right') 

-

        'valign',       (vertical alignment, 'baseline', 'center', or 'top') 

-

        'rotation', 

-

        'zorder',       (precedence of text when stacked with other objs) 

-

        ] 

-

 

-

        """ 

-

        self.msg += "    Attempting to draw an mpl text object\n" 

-

        if not mpltools.check_corners(props['mplobj'], self.mpl_fig): 

-

            warnings.warn("Looks like the annotation(s) you are trying \n" 

-

                          "to draw lies/lay outside the given figure size.\n\n" 

-

                          "Therefore, the resulting Plotly figure may not be \n" 

-

                          "large enough to view the full text. To adjust \n" 

-

                          "the size of the figure, use the 'width' and \n" 

-

                          "'height' keys in the Layout object. Alternatively,\n" 

-

                          "use the Margin object to adjust the figure's margins.") 

-

        align = props['mplobj']._multialignment 

-

        if not align: 

-

            align = props['style']['halign'] # mpl default 

-

        if 'annotations' not in self.plotly_fig['layout']: 

-

            self.plotly_fig['layout']['annotations'] = Annotations() 

-

        if props['text_type'] == 'xlabel': 

-

            self.msg += "      Text object is an xlabel\n" 

-

            self.draw_xlabel(**props) 

-

        elif props['text_type'] == 'ylabel': 

-

            self.msg += "      Text object is a ylabel\n" 

-

            self.draw_ylabel(**props) 

-

        elif props['text_type'] == 'title': 

-

            self.msg += "      Text object is a title\n" 

-

            self.draw_title(**props) 

-

        else:  # just a regular text annotation... 

-

            self.msg += "      Text object is a normal annotation\n" 

-

            if props['coordinates'] is not 'data': 

-

                self.msg += "        Text object isn't linked to 'data' " \ 

-

                            "coordinates\n" 

-

                x_px, y_px = props['mplobj'].get_transform().transform( 

-

                    props['position']) 

-

                x, y = mpltools.display_to_paper(x_px, y_px, 

-

                                              self.plotly_fig['layout']) 

-

                xref = 'paper' 

-

                yref = 'paper' 

-

                xanchor = props['style']['halign']  # no difference here! 

-

                yanchor = mpltools.convert_va(props['style']['valign']) 

-

            else: 

-

                self.msg += "        Text object is linked to 'data' " \ 

-

                            "coordinates\n" 

-

                x, y = props['position'] 

-

                axis_ct = self.axis_ct 

-

                xaxis = self.plotly_fig['layout']['xaxis{0}'.format(axis_ct)] 

-

                yaxis = self.plotly_fig['layout']['yaxis{0}'.format(axis_ct)] 

-

                if (xaxis['range'][0] < x < xaxis['range'][1] 

-

                        and yaxis['range'][0] < y < yaxis['range'][1]): 

-

                    xref = 'x{0}'.format(self.axis_ct) 

-

                    yref = 'y{0}'.format(self.axis_ct) 

-

                else: 

-

                    self.msg += "            Text object is outside " \ 

-

                                "plotting area, making 'paper' reference.\n" 

-

                    x_px, y_px = props['mplobj'].get_transform().transform( 

-

                        props['position']) 

-

                    x, y = mpltools.display_to_paper(x_px, y_px, 

-

                                                     self.plotly_fig['layout']) 

-

                    xref = 'paper' 

-

                    yref = 'paper' 

-

                xanchor = props['style']['halign']  # no difference here! 

-

                yanchor = mpltools.convert_va(props['style']['valign']) 

-

            annotation = Annotation( 

-

                text=props['text'], 

-

                opacity=props['style']['alpha'], 

-

                x=x, 

-

                y=y, 

-

                xref=xref, 

-

                yref=yref, 

-

                align=align, 

-

                xanchor=xanchor, 

-

                yanchor=yanchor, 

-

                showarrow=False,  # change this later? 

-

                font=Font( 

-

                    color=props['style']['color'], 

-

                    size=props['style']['fontsize'] 

-

                ) 

-

            ) 

-

            self.plotly_fig['layout']['annotations'] += annotation, 

-

            self.msg += "    Heck, yeah I drew that annotation\n" 

-

 

-

    def draw_title(self, **props): 

-

        """Add a title to the current subplot in layout dictionary. 

-

 

-

        If there exists more than a single plot in the figure, titles revert 

-

        to 'page'-referenced annotations. 

-

 

-

        props.keys() -- [ 

-

        'text',         (actual content string, not the text obj) 

-

        'position',     (an x, y pair, not an mpl Bbox) 

-

        'coordinates',  ('data', 'axes', 'figure', 'display') 

-

        'text_type',    ('title', 'xlabel', or 'ylabel') 

-

        'style',        (style dict, see below) 

-

        'mplobj'        (actual mpl text object) 

-

        ] 

-

 

-

        props['style'].keys() -- [ 

-

        'alpha',        (opacity of text) 

-

        'fontsize',     (size in points of text) 

-

        'color',        (hex color) 

-

        'halign',       (horizontal alignment, 'left', 'center', or 'right') 

-

        'valign',       (vertical alignment, 'baseline', 'center', or 'top') 

-

        'rotation', 

-

        'zorder',       (precedence of text when stacked with other objs) 

-

        ] 

-

 

-

        """ 

-

        self.msg += "        Attempting to draw a title\n" 

-

        if len(self.mpl_fig.axes) > 1: 

-

            self.msg += "          More than one subplot, adding title as " \ 

-

                        "annotation\n" 

-

            x_px, y_px = props['mplobj'].get_transform().transform(props[ 

-

                'position']) 

-

            x, y = mpltools.display_to_paper(x_px, y_px, 

-

                                             self.plotly_fig['layout']) 

-

            annotation = Annotation( 

-

                text=props['text'], 

-

                font=Font(color=props['style']['color'], 

-

                         size=props['style']['fontsize'] 

-

                ), 

-

                xref='paper', 

-

                yref='paper', 

-

                x=x, 

-

                y=y, 

-

                xanchor='center', 

-

                yanchor='bottom', 

-

                showarrow=False  # no arrow for a title! 

-

            ) 

-

            self.plotly_fig['layout']['annotations'] += annotation, 

-

        else: 

-

            self.msg += "          Only one subplot found, adding as a " \ 

-

                        "plotly title\n" 

-

            self.plotly_fig['layout']['title'] = props['text'] 

-

            titlefont = Font(size=props['style']['fontsize'], 

-

                             color=props['style']['color'] 

-

            ) 

-

            self.plotly_fig['layout']['titlefont'] = titlefont 

-

 

-

    def draw_xlabel(self, **props): 

-

        """Add an xaxis label to the current subplot in layout dictionary. 

-

 

-

        props.keys() -- [ 

-

        'text',         (actual content string, not the text obj) 

-

        'position',     (an x, y pair, not an mpl Bbox) 

-

        'coordinates',  ('data', 'axes', 'figure', 'display') 

-

        'text_type',    ('title', 'xlabel', or 'ylabel') 

-

        'style',        (style dict, see below) 

-

        'mplobj'        (actual mpl text object) 

-

        ] 

-

 

-

        props['style'].keys() -- [ 

-

        'alpha',        (opacity of text) 

-

        'fontsize',     (size in points of text) 

-

        'color',        (hex color) 

-

        'halign',       (horizontal alignment, 'left', 'center', or 'right') 

-

        'valign',       (vertical alignment, 'baseline', 'center', or 'top') 

-

        'rotation', 

-

        'zorder',       (precedence of text when stacked with other objs) 

-

        ] 

-

 

-

        """ 

-

        self.msg += "        Adding xlabel\n" 

-

        axis_key = 'xaxis{0}'.format(self.axis_ct) 

-

        self.plotly_fig['layout'][axis_key]['title'] = props['text'] 

-

        titlefont = Font(size=props['style']['fontsize'], 

-

                         color=props['style']['color']) 

-

        self.plotly_fig['layout'][axis_key]['titlefont'] = titlefont 

-

 

-

    def draw_ylabel(self, **props): 

-

        """Add a yaxis label to the current subplot in layout dictionary. 

-

 

-

        props.keys() -- [ 

-

        'text',         (actual content string, not the text obj) 

-

        'position',     (an x, y pair, not an mpl Bbox) 

-

        'coordinates',  ('data', 'axes', 'figure', 'display') 

-

        'text_type',    ('title', 'xlabel', or 'ylabel') 

-

        'style',        (style dict, see below) 

-

        'mplobj'        (actual mpl text object) 

-

        ] 

-

 

-

        props['style'].keys() -- [ 

-

        'alpha',        (opacity of text) 

-

        'fontsize',     (size in points of text) 

-

        'color',        (hex color) 

-

        'halign',       (horizontal alignment, 'left', 'center', or 'right') 

-

        'valign',       (vertical alignment, 'baseline', 'center', or 'top') 

-

        'rotation', 

-

        'zorder',       (precedence of text when stacked with other objs) 

-

        ] 

-

 

-

        """ 

-

        self.msg += "        Adding ylabel\n" 

-

        axis_key = 'yaxis{0}'.format(self.axis_ct) 

-

        self.plotly_fig['layout'][axis_key]['title'] = props['text'] 

-

        titlefont = Font(size=props['style']['fontsize'], 

-

                         color=props['style']['color']) 

-

        self.plotly_fig['layout'][axis_key]['titlefont'] = titlefont 

-

 

-

    def resize(self): 

-

        """Revert figure layout to allow plotly to resize. 

-

 

-

        By default, PlotlyRenderer tries its hardest to precisely mimic an 

-

        mpl figure. However, plotly is pretty good with aesthetics. By 

-

        running PlotlyRenderer.resize(), layout parameters are deleted. This 

-

        lets plotly choose them instead of mpl. 

-

 

-

        """ 

-

        self.msg += "Resizing figure, deleting keys from layout\n" 

-

        for key in ['width', 'height', 'autosize', 'margin']: 

-

            try: 

-

                del self.plotly_fig['layout'][key] 

-

            except KeyError: 

-

                pass 

-

 

-

    def strip_style(self): 

-

        self.msg += "Stripping mpl style, deleting keys from data and layout\n" 

-

        self.plotly_fig.strip_style() 

- -
-
- - - - - diff --git a/plotly/tests/coverage/plotly_plotly_plotly.html b/plotly/tests/coverage/plotly_plotly_plotly.html deleted file mode 100644 index ff1faf36ae2..00000000000 --- a/plotly/tests/coverage/plotly_plotly_plotly.html +++ /dev/null @@ -1,1472 +0,0 @@ - - - - - - - - Coverage for plotly/plotly/plotly: 61% - - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

-

27

-

28

-

29

-

30

-

31

-

32

-

33

-

34

-

35

-

36

-

37

-

38

-

39

-

40

-

41

-

42

-

43

-

44

-

45

-

46

-

47

-

48

-

49

-

50

-

51

-

52

-

53

-

54

-

55

-

56

-

57

-

58

-

59

-

60

-

61

-

62

-

63

-

64

-

65

-

66

-

67

-

68

-

69

-

70

-

71

-

72

-

73

-

74

-

75

-

76

-

77

-

78

-

79

-

80

-

81

-

82

-

83

-

84

-

85

-

86

-

87

-

88

-

89

-

90

-

91

-

92

-

93

-

94

-

95

-

96

-

97

-

98

-

99

-

100

-

101

-

102

-

103

-

104

-

105

-

106

-

107

-

108

-

109

-

110

-

111

-

112

-

113

-

114

-

115

-

116

-

117

-

118

-

119

-

120

-

121

-

122

-

123

-

124

-

125

-

126

-

127

-

128

-

129

-

130

-

131

-

132

-

133

-

134

-

135

-

136

-

137

-

138

-

139

-

140

-

141

-

142

-

143

-

144

-

145

-

146

-

147

-

148

-

149

-

150

-

151

-

152

-

153

-

154

-

155

-

156

-

157

-

158

-

159

-

160

-

161

-

162

-

163

-

164

-

165

-

166

-

167

-

168

-

169

-

170

-

171

-

172

-

173

-

174

-

175

-

176

-

177

-

178

-

179

-

180

-

181

-

182

-

183

-

184

-

185

-

186

-

187

-

188

-

189

-

190

-

191

-

192

-

193

-

194

-

195

-

196

-

197

-

198

-

199

-

200

-

201

-

202

-

203

-

204

-

205

-

206

-

207

-

208

-

209

-

210

-

211

-

212

-

213

-

214

-

215

-

216

-

217

-

218

-

219

-

220

-

221

-

222

-

223

-

224

-

225

-

226

-

227

-

228

-

229

-

230

-

231

-

232

-

233

-

234

-

235

-

236

-

237

-

238

-

239

-

240

-

241

-

242

-

243

-

244

-

245

-

246

-

247

-

248

-

249

-

250

-

251

-

252

-

253

-

254

-

255

-

256

-

257

-

258

-

259

-

260

-

261

-

262

-

263

-

264

-

265

-

266

-

267

-

268

-

269

-

270

-

271

-

272

-

273

-

274

-

275

-

276

-

277

-

278

-

279

-

280

-

281

-

282

-

283

-

284

-

285

-

286

-

287

-

288

-

289

-

290

-

291

-

292

-

293

-

294

-

295

-

296

-

297

-

298

-

299

-

300

-

301

-

302

-

303

-

304

-

305

-

306

-

307

-

308

-

309

-

310

-

311

-

312

-

313

-

314

-

315

-

316

-

317

-

318

-

319

-

320

-

321

-

322

-

323

-

324

-

325

-

326

-

327

-

328

-

329

-

330

-

331

-

332

-

333

-

334

-

335

-

336

-

337

-

338

-

339

-

340

-

341

-

342

-

343

-

344

-

345

-

346

-

347

-

348

-

349

-

350

-

351

-

352

-

353

-

354

-

355

-

356

-

357

-

358

-

359

-

360

-

361

-

362

-

363

-

364

-

365

-

366

-

367

-

368

-

369

-

370

-

371

-

372

-

373

-

374

-

375

-

376

-

377

-

378

-

379

-

380

-

381

-

382

-

383

-

384

-

385

-

386

-

387

-

388

-

389

-

390

-

391

-

392

-

393

-

394

-

395

-

396

-

397

-

398

-

399

-

400

-

401

-

402

-

403

-

404

-

405

-

406

-

407

-

408

-

409

-

410

-

411

-

412

-

413

-

414

-

415

-

416

-

417

-

418

-

419

-

420

-

421

-

422

-

423

-

424

-

425

-

426

-

427

-

428

-

429

-

430

-

431

-

432

-

433

-

434

-

435

-

436

-

437

-

438

-

439

-

440

-

441

-

442

-

443

-

444

-

445

-

446

-

447

-

448

-

449

-

450

-

451

-

452

-

453

-

454

-

455

-

456

-

457

-

458

-

459

-

460

-

461

-

462

-

463

-

464

-

465

-

466

-

467

-

468

-

469

-

470

-

471

-

472

-

473

-

474

-

475

-

476

-

477

-

478

-

479

-

480

-

481

-

482

-

483

-

484

-

485

-

486

-

487

-

488

-

489

-

490

-

491

-

492

-

493

-

494

-

495

-

496

-

497

-

498

-

499

-

500

-

501

-

502

-

503

-

504

-

505

-

506

-

507

-

508

-

509

-

510

-

511

-

512

-

513

-

514

-

515

-

516

-

517

-

518

-

519

-

520

-

521

-

522

-

523

-

524

-

525

-

526

-

527

-

528

-

529

-

530

-

531

-

532

-

533

-

534

-

535

-

536

-

537

-

538

-

539

-

540

-

541

-

542

-

543

-

544

-

545

-

546

-

547

-

548

-

549

-

550

-

551

-

552

-

553

-

554

-

555

-

556

-

557

-

558

-

559

-

560

-

561

-

562

-

563

-

564

-

565

-

566

-

567

-

568

-

569

-

570

-

571

-

572

-

573

-

574

-

575

-

576

-

577

-

578

-

579

-

580

-

581

-

582

-

583

-

584

-

585

-

586

-

587

-

588

-

589

-

590

-

591

-

592

-

593

-

594

-

595

-

596

-

597

-

598

-

599

-

600

-

601

-

602

-

603

-

604

-

605

-

606

-

607

-

608

-

609

-

610

-

611

-

612

-

613

-

614

-

615

-

616

-

617

-

618

-

619

-

620

-

621

-

622

-

623

-

624

-

625

-

626

-

627

-

628

-

629

-

630

-

631

-

632

-

633

-

634

-

635

-

636

-

637

-

638

-

639

-

640

-

641

-

642

-

643

-

644

-

645

-

646

-

647

-

648

-

649

-

650

-

651

-

652

-

653

-

654

-

655

-

656

-

657

-

658

-

659

-

660

-

661

-

662

-

663

-

664

-

665

-

666

-

667

-

668

-

669

-

670

-

671

-

672

-

673

-

674

-

675

-

676

-

677

-

678

-

679

-

680

-

681

-

682

-

683

-

684

-

685

-

686

-

687

-

688

-

689

-

690

-

691

-

692

-

693

-

694

-

695

- -
-

""" 

-

plotly 

-

====== 

-

 

-

A module that contains the plotly class, a liaison between the user 

-

and ploty's servers. 

-

 

-

1. get DEFAULT_PLOT_OPTIONS for options 

-

 

-

2. update plot_options with .plotly/ dir 

-

 

-

3. update plot_options with _plot_options 

-

 

-

4. update plot_options with kwargs! 

-

 

-

""" 

-

from __future__ import absolute_import 

-

 

-

import json 

-

import warnings 

-

import copy 

-

import os 

-

import six 

-

 

-

import requests 

-

 

-

from plotly.plotly import chunked_requests 

-

from plotly import utils 

-

from plotly import tools 

-

from plotly import exceptions 

-

from plotly import version 

-

 

-

 

-

__all__ = ["sign_in", "update_plot_options", "get_plot_options", 

-

           "get_credentials", "iplot", "plot", "iplot_mpl", "plot_mpl", 

-

           "get_figure", "Stream", "image"] 

-

 

-

_DEFAULT_PLOT_OPTIONS = dict( 

-

    filename="plot from API", 

-

    fileopt="new", 

-

    world_readable=True, 

-

    auto_open=True, 

-

    validate=True) 

-

 

-

_credentials = dict() 

-

 

-

_plot_options = dict() 

-

 

-

### test file permissions and make sure nothing is corrupted ### 

-

tools.ensure_local_plotly_files() 

-

 

-

### _credentials stuff ### 

-

 

-

 

-

def sign_in(username, api_key): 

-

    """Set module-scoped _credentials for session. Verify with plotly.""" 

-

    global _credentials 

-

    _credentials['username'], _credentials['api_key'] = username, api_key 

-

    # TODO: verify these _credentials with plotly 

-

 

-

 

-

### plot options stuff ### 

-

 

-

def update_plot_options(**kwargs): 

-

    """ Update the module-level _plot_options 

-

    """ 

-

    global _plot_options 

-

    _plot_options.update(kwargs) 

-

 

-

 

-

def get_plot_options(): 

-

    """ Returns a copy of the user supplied plot options. 

-

    Use `update_plot_options()` to change. 

-

    """ 

-

    global _plot_options 

-

    return copy.copy(_plot_options) 

-

 

-

 

-

def get_credentials(): 

-

    """ Returns a copy of the user supplied credentials. 

-

    """ 

-

    global _credentials 

-

    if ('username' in _credentials) and ('api_key' in _credentials): 

-

        return copy.copy(_credentials) 

-

    else: 

-

        return tools.get_credentials_file() 

-

 

-

 

-

### plot stuff ### 

-

 

-

def iplot(figure_or_data, **plot_options): 

-

    """Create a unique url for this plot in Plotly and open in IPython. 

-

 

-

    plot_options keyword agruments: 

-

    filename (string) -- the name that will be associated with this figure 

-

    fileopt ('new' | 'overwrite' | 'extend' | 'append') -- 'new' creates a 

-

        'new': create a new, unique url for this plot 

-

        'overwrite': overwrite the file associated with `filename` with this 

-

        'extend': add additional numbers (data) to existing traces 

-

        'append': add additional traces to existing data lists 

-

    world_readable (default=True) -- make this figure private/public 

-

 

-

    """ 

-

    if 'auto_open' not in plot_options: 

-

        plot_options['auto_open'] = False 

-

    res = plot(figure_or_data, **plot_options) 

-

    urlsplit = res.split('/') 

-

    username, plot_id = urlsplit[-2][1:], urlsplit[-1]  # TODO: HACKY! 

-

 

-

    embed_options = dict() 

-

    if 'width' in plot_options: 

-

        embed_options['width'] = plot_options['width'] 

-

    if 'height' in plot_options: 

-

        embed_options['height'] = plot_options['height'] 

-

 

-

    return tools.embed(username, plot_id, **embed_options) 

-

 

-

 

-

def _plot_option_logic(plot_options): 

-

    """Sets plot_options via a precedence hierarchy.""" 

-

    options = dict() 

-

    options.update(_DEFAULT_PLOT_OPTIONS) 

-

    options.update(_plot_options) 

-

    options.update(plot_options) 

-

    if ('filename' in plot_options 

-

       and 'fileopt' not in _plot_options 

-

       and 'fileopt' not in plot_options): 

-

        options['fileopt'] = 'overwrite' 

-

    return options 

-

 

-

 

-

def plot(figure_or_data, validate=True, **plot_options): 

-

    """Create a unique url for this plot in Plotly and optionally open url. 

-

 

-

    plot_options keyword agruments: 

-

    filename (string) -- the name that will be associated with this figure 

-

    fileopt ('new' | 'overwrite' | 'extend' | 'append') -- 'new' creates a 

-

        'new': create a new, unique url for this plot 

-

        'overwrite': overwrite the file associated with `filename` with this 

-

        'extend': add additional numbers (data) to existing traces 

-

        'append': add additional traces to existing data lists 

-

    world_readable (default=True) -- make this figure private/public 

-

    auto_open (default=True) -- Toggle browser options 

-

        True: open this plot in a new browser tab 

-

        False: do not open plot in the browser, but do return the unique url 

-

 

-

    """ 

-

    if isinstance(figure_or_data, dict): 

-

        figure = figure_or_data 

-

    elif isinstance(figure_or_data, list): 

-

        figure = {'data': figure_or_data} 

-

    else: 

-

        raise exceptions.PlotlyError("The `figure_or_data` positional argument " 

-

                                     "must be either `dict`-like or " 

-

                                     "`list`-like.") 

-

    if validate: 

-

        try: 

-

            tools.validate(figure, obj_type='Figure') 

-

        except exceptions.PlotlyError as err: 

-

            raise exceptions.PlotlyError("Invalid 'figure_or_data' argument. " 

-

                                         "Plotly will not be able to properly " 

-

                                         "parse the resulting JSON. If you " 

-

                                         "want to send this 'figure_or_data' " 

-

                                         "to Plotly anyway (not recommended), " 

-

                                         "you can set 'validate=False' as a " 

-

                                         "plot option.\nHere's why you're " 

-

                                         "seeing this error:\n\n{}".format(err)) 

-

    for entry in figure['data']: 

-

        for key, val in list(entry.items()): 

-

            try: 

-

                if len(val) > 40000: 

-

                    msg = ("Woah there! Look at all those points! Due to " 

-

                           "browser limitations, Plotly has a hard time " 

-

                           "graphing more than 500k data points for line " 

-

                           "charts, or 40k points for other types of charts. " 

-

                           "Here are some suggestions:\n" 

-

                           "(1) Trying using the image API to return an image " 

-

                           "instead of a graph URL\n" 

-

                           "(2) Use matplotlib\n" 

-

                           "(3) See if you can create your visualization with " 

-

                           "fewer data points\n\n" 

-

                           "If the visualization you're using aggregates " 

-

                           "points (e.g., box plot, histogram, etc.) you can " 

-

                           "disregard this warning.") 

-

                    warnings.warn(msg) 

-

            except TypeError: 

-

                pass 

-

    plot_options = _plot_option_logic(plot_options) 

-

    res = _send_to_plotly(figure, **plot_options) 

-

    if res['error'] == '': 

-

        if plot_options['auto_open']: 

-

            try: 

-

                from webbrowser import open as wbopen 

-

                wbopen(res['url']) 

-

            except:  # TODO: what should we except here? this is dangerous 

-

                pass 

-

        return res['url'] 

-

    else: 

-

        raise exceptions.PlotlyAccountError(res['error']) 

-

 

-

 

-

def iplot_mpl(fig, resize=True, strip_style=False, update=None, **plot_options): 

-

    """Replot a matplotlib figure with plotly in IPython. 

-

 

-

    This function: 

-

    1. converts the mpl figure into JSON (run help(plolty.tools.mpl_to_plotly)) 

-

    2. makes a request to Plotly to save this figure in your account 

-

    3. displays the image in your IPython output cell 

-

 

-

    Positional agruments: 

-

    fig -- a figure object from matplotlib 

-

 

-

    Keyword arguments: 

-

    resize (default=True) -- allow plotly to choose the figure size 

-

    strip_style (default=False) -- allow plotly to choose style options 

-

    update (default=None) -- update the resulting figure with an 'update' 

-

        dictionary-like object resembling a plotly 'Figure' object 

-

 

-

    Additional keyword arguments: 

-

    plot_options -- run help(plotly.plotly.iplot) 

-

 

-

    """ 

-

    fig = tools.mpl_to_plotly(fig, resize=resize, strip_style=strip_style) 

-

    if update and isinstance(update, dict): 

-

        try: 

-

            fig.update(update) 

-

            fig.validate() 

-

        except exceptions.PlotlyGraphObjectError as err: 

-

            err.add_note("Your updated figure could not be properly validated.") 

-

            err.prepare() 

-

            raise 

-

    elif update is not None: 

-

        raise exceptions.PlotlyGraphObjectError( 

-

            "'update' must be dictionary-like and a valid plotly Figure " 

-

            "object. Run 'help(plotly.graph_objs.Figure)' for more info." 

-

        ) 

-

    return iplot(fig, **plot_options) 

-

 

-

 

-

def plot_mpl(fig, resize=True, strip_style=False, update=None, **plot_options): 

-

    """Replot a matplotlib figure with plotly. 

-

 

-

    This function: 

-

    1. converts the mpl figure into JSON (run help(plolty.tools.mpl_to_plotly)) 

-

    2. makes a request to Plotly to save this figure in your account 

-

    3. opens your figure in a browser tab OR returns the unique figure url 

-

 

-

    Positional agruments: 

-

    fig -- a figure object from matplotlib 

-

 

-

    Keyword arguments: 

-

    resize (default=True) -- allow plotly to choose the figure size 

-

    strip_style (default=False) -- allow plotly to choose style options 

-

    update (default=None) -- update the resulting figure with an 'update' 

-

        dictionary-like object resembling a plotly 'Figure' object 

-

 

-

    Additional keyword arguments: 

-

    plot_options -- run help(plotly.plotly.plot) 

-

 

-

    """ 

-

    fig = tools.mpl_to_plotly(fig, resize=resize, strip_style=strip_style) 

-

    if update and isinstance(update, dict): 

-

        try: 

-

            fig.update(update) 

-

            fig.validate() 

-

        except exceptions.PlotlyGraphObjectError as err: 

-

            err.add_note("Your updated figure could not be properly validated.") 

-

            err.prepare() 

-

            raise 

-

    elif update is not None: 

-

        raise exceptions.PlotlyGraphObjectError( 

-

            "'update' must be dictionary-like and a valid plotly Figure " 

-

            "object. Run 'help(plotly.graph_objs.Figure)' for more info." 

-

        ) 

-

    return plot(fig, **plot_options) 

-

 

-

 

-

def get_figure(file_owner_or_url, file_id=None, raw=False): 

-

    """Returns a JSON figure representation for the specified file 

-

 

-

    Plotly uniquely identifies figures with a 'file_owner'/'file_id' pair. 

-

    Since each file is given a corresponding unique url, you may also simply 

-

    pass a valid plotly url as the first argument. 

-

 

-

    Note, if you're using a file_owner string as the first argument, you MUST 

-

    specify a `file_id` keyword argument. Else, if you're using a url string 

-

    as the first argument, you MUST NOT specify a `file_id` keyword argument, or 

-

    file_id must be set to Python's None value. 

-

 

-

    Positional arguments: 

-

    file_owner_or_url (string) -- a valid plotly username OR a valid plotly url 

-

 

-

    Keyword arguments: 

-

    file_id (default=None) -- an int or string that can be converted to int 

-

                              if you're using a url, don't fill this in! 

-

    raw (default=False) -- if true, return unicode JSON string verbatim** 

-

 

-

    **by default, plotly will return a Figure object (run help(plotly 

-

    .graph_objs.Figure)). This representation decodes the keys and values from 

-

    unicode (if possible), removes information irrelevant to the figure 

-

    representation, and converts the JSON dictionary objects to plotly 

-

    `graph objects`. 

-

 

-

    """ 

-

    plotly_rest_url = tools.get_config_file()['plotly_domain'] 

-

    if file_id is None:  # assume we're using a url 

-

        url = file_owner_or_url 

-

        if url[:len(plotly_rest_url)] != plotly_rest_url: 

-

            raise exceptions.PlotlyError( 

-

                "Because you didn't supply a 'file_id' in the call, " 

-

                "we're assuming you're trying to snag a figure from a url. " 

-

                "You supplied the url, '{}', we expected it to start with '{}'." 

-

                "\nRun help on this function for more information." 

-

                "".format(url, plotly_rest_url)) 

-

        head = plotly_rest_url + "/~" 

-

        file_owner = url.replace(head, "").split('/')[0] 

-

        file_id = url.replace(head, "").split('/')[1] 

-

    else: 

-

        file_owner = file_owner_or_url 

-

    resource = "/apigetfile/{username}/{file_id}".format(username=file_owner, 

-

                                                         file_id=file_id) 

-

    (username, api_key) = _validation_key_logic() 

-

    headers = {'plotly-username': username, 

-

               'plotly-apikey': api_key, 

-

               'plotly-version': version.__version__, 

-

               'plotly-platform': 'python'} 

-

    try: 

-

        test_if_int = int(file_id) 

-

    except ValueError: 

-

        raise exceptions.PlotlyError( 

-

            "The 'file_id' argument was not able to be converted into an " 

-

            "integer number. Make sure that the positional 'file_id' argument " 

-

            "is a number that can be converted into an integer or a string " 

-

            "that can be converted into an integer." 

-

        ) 

-

    if int(file_id) < 0: 

-

        raise exceptions.PlotlyError( 

-

            "The 'file_id' argument must be a non-negative number." 

-

        ) 

-

    response = requests.get(plotly_rest_url + resource, headers=headers) 

-

    if response.status_code == 200: 

-

        if six.PY3: 

-

            content = json.loads(response.content.decode('unicode_escape')) 

-

        else: 

-

            content = json.loads(response.content) 

-

        response_payload = content['payload'] 

-

        figure = response_payload['figure'] 

-

        utils.decode_unicode(figure) 

-

        if raw: 

-

            return figure 

-

        else: 

-

            return tools.get_valid_graph_obj(figure, obj_type='Figure') 

-

    else: 

-

        try: 

-

            content = json.loads(response.content) 

-

            raise exceptions.PlotlyError(content) 

-

        except: 

-

            raise exceptions.PlotlyError( 

-

                "There was an error retrieving this file") 

-

 

-

 

-

@utils.template_doc(**tools.get_config_file()) 

-

class Stream: 

-

    """ Interface to Plotly's real-time graphing API. 

-

 

-

    Initialize a Stream object with a stream_id 

-

    found in {plotly_domain}/settings. 

-

    Real-time graphs are initialized with a call to `plot` that embeds 

-

    your unique `stream_id`s in each of the graph's traces. The `Stream` 

-

    interface plots data to these traces, as identified with the unique 

-

    stream_id, in real-time. 

-

    Every viewer of the graph sees the same data at the same time. 

-

 

-

    View examples and tutorials here: 

-

    http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s7_streaming/s7_streaming.ipynb 

-

 

-

    Stream example: 

-

    # Initialize a streaming graph 

-

    # by embedding stream_id's in the graph's traces 

-

    >>> stream_id = "your_stream_id" # See {plotly_domain}/settings 

-

    >>> py.plot(Data([Scatter(x=[], 

-

                              y=[], 

-

                              stream=dict(token=stream_id, maxpoints=100))]) 

-

    # Stream data to the import trace 

-

    >>> stream = Stream(stream_id) # Initialize a stream object 

-

    >>> stream.open() # Open the stream 

-

    >>> stream.write(dict(x=1, y=1)) # Plot (1, 1) in your graph 

-

    """ 

-

 

-

    @utils.template_doc(**tools.get_config_file()) 

-

    def __init__(self, stream_id): 

-

        """ Initialize a Stream object with your unique stream_id. 

-

        Find your stream_id at {plotly_domain}/settings. 

-

 

-

        For more help, see: `help(plotly.plotly.Stream)` 

-

        or see examples and tutorials here: 

-

        http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s7_streaming/s7_streaming.ipynb 

-

        """ 

-

        self.stream_id = stream_id 

-

        self.connected = False 

-

 

-

    def open(self): 

-

        """Open streaming connection to plotly. 

-

 

-

        For more help, see: `help(plotly.plotly.Stream)` 

-

        or see examples and tutorials here: 

-

        http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s7_streaming/s7_streaming.ipynb 

-

        """ 

-

 

-

        streaming_url = tools.get_config_file()['plotly_streaming_domain'] 

-

        self._stream = chunked_requests.Stream(streaming_url, 

-

                                               80, 

-

                                               {'Host': streaming_url, 

-

                                                'plotly-streamtoken': self.stream_id}) 

-

 

-

    def write(self, trace, layout=None, validate=True, 

-

              reconnect_on=(200, '', 408)): 

-

        """Write to an open stream. 

-

 

-

        Once you've instantiated a 'Stream' object with a 'stream_id', 

-

        you can 'write' to it in real time. 

-

 

-

        positional arguments: 

-

        trace - A valid plotly trace object (e.g., Scatter, Heatmap, etc.). 

-

                Not all keys in these are `stremable` run help(Obj) on the type 

-

                of trace your trying to stream, for each valid key, if the key 

-

                is streamable, it will say 'streamable = True'. Trace objects 

-

                must be dictionary-like. 

-

 

-

        keyword arguments: 

-

        layout (default=None) - A valid Layout object 

-

                                Run help(plotly.graph_objs.Layout) 

-

        validate (default = True) - Validate this stream before sending? 

-

                                    This will catch local errors if set to True. 

-

 

-

        Some valid keys for trace dictionaries: 

-

            'x', 'y', 'text', 'z', 'marker', 'line' 

-

 

-

        Examples: 

-

        >>> write(dict(x=1, y=2))  # assumes 'scatter' type 

-

        >>> write(Bar(x=[1, 2, 3], y=[10, 20, 30])) 

-

        >>> write(Scatter(x=1, y=2, text='scatter text')) 

-

        >>> write(Scatter(x=1, y=3, marker=Marker(color='blue'))) 

-

        >>> write(Heatmap(z=[[1, 2, 3], [4, 5, 6]])) 

-

 

-

        The connection to plotly's servers is checked before writing 

-

        and reconnected if disconnected and if the response status code 

-

        is in `reconnect_on`. 

-

 

-

        For more help, see: `help(plotly.plotly.Stream)` 

-

        or see examples and tutorials here: 

-

        http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s7_streaming/s7_streaming.ipynb 

-

        """ 

-

        stream_object = dict() 

-

        stream_object.update(trace) 

-

        if 'type' not in stream_object: 

-

            stream_object['type'] = 'scatter' 

-

        if validate: 

-

            try: 

-

                tools.validate(stream_object, stream_object['type']) 

-

            except exceptions.PlotlyError as err: 

-

                raise exceptions.PlotlyError( 

-

                    "Part of the data object with type, '{}', is invalid. This " 

-

                    "will default to 'scatter' if you do not supply a 'type'. " 

-

                    "If you do not want to validate your data objects when " 

-

                    "streaming, you can set 'validate=False' in the call to " 

-

                    "'your_stream.write()'. Here's why the object is " 

-

                    "invalid:\n\n{}".format(stream_object['type'], err) 

-

                ) 

-

            try: 

-

                tools.validate_stream(stream_object, stream_object['type']) 

-

            except exceptions.PlotlyError as err: 

-

                raise exceptions.PlotlyError( 

-

                    "Part of the data object with type, '{}', cannot yet be " 

-

                    "streamed into Plotly. If you do not want to validate your " 

-

                    "data objects when streaming, you can set 'validate=False' " 

-

                    "in the call to 'your_stream.write()'. Here's why the " 

-

                    "object cannot be streamed:\n\n{}" 

-

                    "".format(stream_object['type'], err) 

-

                ) 

-

            if layout is not None: 

-

                try: 

-

                    tools.validate(layout, 'Layout') 

-

                except exceptions.PlotlyError as err: 

-

                    raise exceptions.PlotlyError( 

-

                        "Your layout kwarg was invalid. " 

-

                        "Here's why:\n\n{}".format(err) 

-

                    ) 

-

        del stream_object['type'] 

-

 

-

        if layout is not None: 

-

            stream_object.update(dict(layout=layout)) 

-

 

-

        # TODO: allow string version of this? 

-

        jdata = json.dumps(stream_object, cls=utils._plotlyJSONEncoder) 

-

        jdata += "\n" 

-

 

-

        try: 

-

            self._stream.write(jdata, reconnect_on=reconnect_on) 

-

        except AttributeError: 

-

            raise exceptions.PlotlyError("Stream has not been opened yet, " 

-

                                         "cannot write to a closed connection. " 

-

                                         "Call `open()` on the stream to open the stream.") 

-

 

-

    def close(self): 

-

        """ Close the stream connection to plotly's streaming servers. 

-

 

-

        For more help, see: `help(plotly.plotly.Stream)` 

-

        or see examples and tutorials here: 

-

        http://nbviewer.ipython.org/github/plotly/python-user-guide/blob/master/s7_streaming/s7_streaming.ipynb 

-

        """ 

-

        try: 

-

            self._stream.close() 

-

        except AttributeError: 

-

            raise exceptions.PlotlyError("Stream has not been opened yet.") 

-

 

-

 

-

class image: 

-

    ''' Helper functions wrapped around plotly's static image generation api. 

-

    ''' 

-

 

-

    @staticmethod 

-

    def get(figure_or_data, format='png', width=None, height=None): 

-

        """ Return a static image of the plot described by `figure`. 

-

 

-

        Valid formats: 'png', 'svg', 'jpeg', 'pdf' 

-

        """ 

-

        if isinstance(figure_or_data, dict): 

-

            figure = figure_or_data 

-

        elif isinstance(figure_or_data, list): 

-

            figure = {'data': figure_or_data} 

-

 

-

        if format not in ['png', 'svg', 'jpeg', 'pdf']: 

-

            raise exceptions.PlotlyError("Invalid format. " 

-

                                         "This version of your Plotly-Python " 

-

                                         "package currently only supports " 

-

                                         "png, svg, jpeg, and pdf. " 

-

                                         "Learn more about image exporting, " 

-

                                         "and the currently supported file " 

-

                                         "types here: " 

-

                                         "https://plot.ly/python/static-image-export/") 

-

 

-

        (username, api_key) = _validation_key_logic() 

-

        headers = {'plotly-username': username, 

-

                   'plotly-apikey': api_key, 

-

                   'plotly-version': version.__version__, 

-

                   'plotly-platform': 'python'} 

-

 

-

        payload = { 

-

            'figure': figure, 

-

            'format': format 

-

        } 

-

 

-

        if width is not None: 

-

            payload['width'] = width 

-

        if height is not None: 

-

            payload['height'] = height 

-

 

-

        url = tools.get_config_file()['plotly_domain'] + "/apigenimage/" 

-

        res = requests.post(url, 

-

                            data=json.dumps(payload, 

-

                                            cls=utils._plotlyJSONEncoder), 

-

                            headers=headers) 

-

 

-

        headers = res.headers 

-

 

-

        if res.status_code == 200: 

-

            if ('content-type' in headers and 

-

                headers['content-type'] in ['image/png', 'image/jpeg', 

-

                                            'application/pdf', 

-

                                            'image/svg+xml']): 

-

                return res.content 

-

 

-

            elif ('content-type' in headers and 

-

                  'json' in headers['content-type']): 

-

                return_data = json.loads(res.content) 

-

                return return_data['image'] 

-

        else: 

-

            try: 

-

                if ('content-type' in headers and 

-

                    'json' in headers['content-type']): 

-

                    return_data = json.loads(res.content) 

-

                else: 

-

                    return_data = {'error': res.content} 

-

            except: 

-

                raise exceptions.PlotlyError("The response " 

-

                                             "from plotly could " 

-

                                             "not be translated.") 

-

            raise exceptions.PlotlyError(return_data['error']) 

-

 

-

 

-

    @classmethod 

-

    def ishow(cls, figure_or_data, format='png', width=None, height=None): 

-

        """ Display a static image of the plot described by `figure` 

-

        in an IPython Notebook. 

-

        """ 

-

        if format == 'pdf': 

-

            raise exceptions.PlotlyError("Aw, snap! " 

-

                "It's not currently possible to embed a pdf into " 

-

                "an IPython notebook. You can save the pdf " 

-

                "with the `image.save_as` or you can " 

-

                "embed an png, jpeg, or svg.") 

-

        img = cls.get(figure_or_data, format, width, height) 

-

        from IPython.display import display, Image, SVG 

-

        if format == 'svg': 

-

            display(SVG(img)) 

-

        else: 

-

            display(Image(img)) 

-

 

-

    @classmethod 

-

    def save_as(cls, figure_or_data, filename, format=None, width=None, height=None): 

-

        """ Save a static image of the plot described by `figure` locally as `filename`. 

-

            Valid image formats are 'png', 'svg', 'jpeg', and 'pdf'. 

-

            The format is taken as the extension of the filename or as the supplied format. 

-

        """ 

-

        (base, ext) = os.path.splitext(filename) 

-

        if not ext and not format: 

-

            filename += '.png' 

-

        elif ext and not format: 

-

            format = ext[1:] 

-

        elif not ext and format: 

-

            filename += '.'+format 

-

        else: 

-

            filename += '.'+format 

-

 

-

        img = cls.get(figure_or_data, format, width, height) 

-

 

-

        f = open(filename, 'wb') 

-

        f.write(img) 

-

        f.close() 

-

 

-

 

-

def _send_to_plotly(figure, **plot_options): 

-

    """ 

-

    """ 

-

    fig = tools._replace_newline(figure)  # does not mutate figure 

-

    data = json.dumps(fig['data'] if 'data' in fig else [], 

-

                      cls=utils._plotlyJSONEncoder) 

-

    file_credentials = tools.get_credentials_file() 

-

    if ('username' in _credentials) and ('api_key' in _credentials): 

-

        username, api_key = _credentials['username'], _credentials['api_key'] 

-

    elif ('username' in file_credentials) and ('api_key' in file_credentials): 

-

        (username, api_key) = (file_credentials['username'], 

-

                               file_credentials['api_key']) 

-

    else: 

-

        raise exceptions.PlotlyLocalCredentialsError() 

-

 

-

    kwargs = json.dumps(dict(filename=plot_options['filename'], 

-

                             fileopt=plot_options['fileopt'], 

-

                             world_readable=plot_options['world_readable'], 

-

                             layout=fig['layout'] if 'layout' in fig 

-

                             else {}), 

-

                        cls=utils._plotlyJSONEncoder) 

-

 

-

 

-

    payload = dict(platform='python', # TODO: It'd be cool to expose the platform for RaspPi and others 

-

                   version=version.__version__, 

-

                   args=data, 

-

                   un=username, 

-

                   key=api_key, 

-

                   origin='plot', 

-

                   kwargs=kwargs) 

-

 

-

    url = tools.get_config_file()['plotly_domain'] + "/clientresp" 

-

 

-

    r = requests.post(url, data=payload) 

-

    r.raise_for_status() 

-

    r = json.loads(r.text) 

-

    if 'error' in r and r['error'] != '': 

-

        print((r['error'])) 

-

    if 'warning' in r and r['warning'] != '': 

-

        warnings.warn(r['warning']) 

-

    if 'message' in r and r['message'] != '': 

-

        print((r['message'])) 

-

 

-

    return r 

-

 

-

 

-

def _validation_key_logic(): 

-

    creds_on_file = tools.get_credentials_file() 

-

    if 'username' in _credentials: 

-

        username = _credentials['username'] 

-

    elif 'username' in creds_on_file: 

-

        username = creds_on_file['username'] 

-

    else: 

-

        username = None 

-

    if 'api_key' in _credentials: 

-

        api_key = _credentials['api_key'] 

-

    elif 'api_key' in creds_on_file: 

-

        api_key = creds_on_file['api_key'] 

-

    else: 

-

        api_key = None 

-

    if username is None or api_key is None: 

-

        raise exceptions.PlotlyLocalCredentialsError() 

-

    return (username, api_key) 

- -
-
- - - - - diff --git a/plotly/tests/coverage/plotly_tools.html b/plotly/tests/coverage/plotly_tools.html deleted file mode 100644 index d58a73805f9..00000000000 --- a/plotly/tests/coverage/plotly_tools.html +++ /dev/null @@ -1,1146 +0,0 @@ - - - - - - - - Coverage for plotly/tools: 78% - - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

-

27

-

28

-

29

-

30

-

31

-

32

-

33

-

34

-

35

-

36

-

37

-

38

-

39

-

40

-

41

-

42

-

43

-

44

-

45

-

46

-

47

-

48

-

49

-

50

-

51

-

52

-

53

-

54

-

55

-

56

-

57

-

58

-

59

-

60

-

61

-

62

-

63

-

64

-

65

-

66

-

67

-

68

-

69

-

70

-

71

-

72

-

73

-

74

-

75

-

76

-

77

-

78

-

79

-

80

-

81

-

82

-

83

-

84

-

85

-

86

-

87

-

88

-

89

-

90

-

91

-

92

-

93

-

94

-

95

-

96

-

97

-

98

-

99

-

100

-

101

-

102

-

103

-

104

-

105

-

106

-

107

-

108

-

109

-

110

-

111

-

112

-

113

-

114

-

115

-

116

-

117

-

118

-

119

-

120

-

121

-

122

-

123

-

124

-

125

-

126

-

127

-

128

-

129

-

130

-

131

-

132

-

133

-

134

-

135

-

136

-

137

-

138

-

139

-

140

-

141

-

142

-

143

-

144

-

145

-

146

-

147

-

148

-

149

-

150

-

151

-

152

-

153

-

154

-

155

-

156

-

157

-

158

-

159

-

160

-

161

-

162

-

163

-

164

-

165

-

166

-

167

-

168

-

169

-

170

-

171

-

172

-

173

-

174

-

175

-

176

-

177

-

178

-

179

-

180

-

181

-

182

-

183

-

184

-

185

-

186

-

187

-

188

-

189

-

190

-

191

-

192

-

193

-

194

-

195

-

196

-

197

-

198

-

199

-

200

-

201

-

202

-

203

-

204

-

205

-

206

-

207

-

208

-

209

-

210

-

211

-

212

-

213

-

214

-

215

-

216

-

217

-

218

-

219

-

220

-

221

-

222

-

223

-

224

-

225

-

226

-

227

-

228

-

229

-

230

-

231

-

232

-

233

-

234

-

235

-

236

-

237

-

238

-

239

-

240

-

241

-

242

-

243

-

244

-

245

-

246

-

247

-

248

-

249

-

250

-

251

-

252

-

253

-

254

-

255

-

256

-

257

-

258

-

259

-

260

-

261

-

262

-

263

-

264

-

265

-

266

-

267

-

268

-

269

-

270

-

271

-

272

-

273

-

274

-

275

-

276

-

277

-

278

-

279

-

280

-

281

-

282

-

283

-

284

-

285

-

286

-

287

-

288

-

289

-

290

-

291

-

292

-

293

-

294

-

295

-

296

-

297

-

298

-

299

-

300

-

301

-

302

-

303

-

304

-

305

-

306

-

307

-

308

-

309

-

310

-

311

-

312

-

313

-

314

-

315

-

316

-

317

-

318

-

319

-

320

-

321

-

322

-

323

-

324

-

325

-

326

-

327

-

328

-

329

-

330

-

331

-

332

-

333

-

334

-

335

-

336

-

337

-

338

-

339

-

340

-

341

-

342

-

343

-

344

-

345

-

346

-

347

-

348

-

349

-

350

-

351

-

352

-

353

-

354

-

355

-

356

-

357

-

358

-

359

-

360

-

361

-

362

-

363

-

364

-

365

-

366

-

367

-

368

-

369

-

370

-

371

-

372

-

373

-

374

-

375

-

376

-

377

-

378

-

379

-

380

-

381

-

382

-

383

-

384

-

385

-

386

-

387

-

388

-

389

-

390

-

391

-

392

-

393

-

394

-

395

-

396

-

397

-

398

-

399

-

400

-

401

-

402

-

403

-

404

-

405

-

406

-

407

-

408

-

409

-

410

-

411

-

412

-

413

-

414

-

415

-

416

-

417

-

418

-

419

-

420

-

421

-

422

-

423

-

424

-

425

-

426

-

427

-

428

-

429

-

430

-

431

-

432

-

433

-

434

-

435

-

436

-

437

-

438

-

439

-

440

-

441

-

442

-

443

-

444

-

445

-

446

-

447

-

448

-

449

-

450

-

451

-

452

-

453

-

454

-

455

-

456

-

457

-

458

-

459

-

460

-

461

-

462

-

463

-

464

-

465

-

466

-

467

-

468

-

469

-

470

-

471

-

472

-

473

-

474

-

475

-

476

-

477

-

478

-

479

-

480

-

481

-

482

-

483

-

484

-

485

-

486

-

487

-

488

-

489

-

490

-

491

-

492

-

493

-

494

-

495

-

496

-

497

-

498

-

499

-

500

-

501

-

502

-

503

-

504

-

505

-

506

-

507

-

508

-

509

-

510

-

511

-

512

-

513

-

514

-

515

-

516

-

517

-

518

-

519

-

520

-

521

-

522

-

523

-

524

-

525

-

526

-

527

-

528

-

529

-

530

-

531

-

532

- -
-

# -*- coding: utf-8 -*- 

-

 

-

""" 

-

tools 

-

===== 

-

 

-

Functions that USERS will possibly want access to. 

-

 

-

""" 

-

from __future__ import absolute_import 

-

 

-

import os 

-

import os.path 

-

import warnings 

-

import six 

-

 

-

from plotly import utils 

-

from plotly import exceptions 

-

 

-

from . import matplotlylib 

-

from . graph_objs import graph_objs 

-

 

-

# Warning format 

-

def warning_on_one_line(message, category, filename, lineno, file=None, line=None): 

-

    return '%s:%s: %s:\n\n%s\n\n' % (filename, lineno, category.__name__, message) 

-

warnings.formatwarning = warning_on_one_line 

-

 

-

try: 

-

    _matplotlylib_imported = True 

-

except ImportError: 

-

    _matplotlylib_imported = False 

-

 

-

PLOTLY_DIR = os.path.join(os.path.expanduser("~"), ".plotly") 

-

CREDENTIALS_FILE = os.path.join(PLOTLY_DIR, ".credentials") 

-

CONFIG_FILE = os.path.join(PLOTLY_DIR, ".config") 

-

TEST_DIR = os.path.join(os.path.expanduser("~"), ".test") 

-

TEST_FILE = os.path.join(PLOTLY_DIR, ".permission_test") 

-

 

-

# this sets both the DEFAULTS and the TYPES for these items 

-

_FILE_CONTENT = {CREDENTIALS_FILE: {'username': '', 

-

                                    'api_key': '', 

-

                                    'stream_ids': []}, 

-

                 CONFIG_FILE: {'plotly_domain': 'https://plot.ly', 

-

                               'plotly_streaming_domain': 'stream.plot.ly'}} 

-

 

-

try: 

-

    os.mkdir(TEST_DIR) 

-

    os.rmdir(TEST_DIR) 

-

    if not os.path.exists(PLOTLY_DIR): 

-

        os.mkdir(PLOTLY_DIR) 

-

    f = open(TEST_FILE, 'w') 

-

    f.write('testing\n') 

-

    f.close() 

-

    os.remove(TEST_FILE) 

-

    _file_permissions = True 

-

except: 

-

    _file_permissions = False 

-

 

-

 

-

def check_file_permissions(): 

-

    return _file_permissions 

-

 

-

 

-

def ensure_local_plotly_files(): 

-

    """Ensure that filesystem is setup/filled out in a valid way""" 

-

    if _file_permissions: 

-

        if not os.path.isdir(PLOTLY_DIR): 

-

            os.mkdir(PLOTLY_DIR) 

-

        for fn in [CREDENTIALS_FILE, CONFIG_FILE]: 

-

            contents = utils.load_json_dict(fn) 

-

            for key, val in list(_FILE_CONTENT[fn].items()): 

-

                # TODO: removed type checking below, may want to revisit 

-

                if key not in contents: 

-

                    contents[key] = val 

-

            contents_keys = list(contents.keys()) 

-

            for key in contents_keys: 

-

                if key not in _FILE_CONTENT[fn]: 

-

                    del contents[key] 

-

            utils.save_json_dict(fn, contents) 

-

    else: 

-

        warnings.warn("Looks like you don't have 'read-write' permission to " 

-

                      "your 'home' ('~') directory or to our '~/.plotly' " 

-

                      "directory. That means plotly's python api can't setup " 

-

                      "local configuration files. No problem though! You'll " 

-

                      "just have to sign-in using 'plotly.sign_in()'. For help " 

-

                      "with that: 'help(plotly.sign_in)'." 

-

                      "\nQuestions? support@plot.ly") 

-

 

-

 

-

### credentials tools ### 

-

 

-

def set_credentials_file(username=None, api_key=None, stream_ids=None): 

-

    """Set the keyword-value pairs in `~/.plotly_credentials`. 

-

 

-

    """ 

-

    if not _file_permissions: 

-

        raise exceptions.PlotlyError("You don't have proper file permissions " 

-

                                     "to run this function.") 

-

    ensure_local_plotly_files()  # make sure what's there is OK 

-

    credentials = get_credentials_file() 

-

    if isinstance(username, six.string_types): 

-

        credentials['username'] = username 

-

    if isinstance(api_key, six.string_types): 

-

        credentials['api_key'] = api_key 

-

    if isinstance(stream_ids, (list, tuple)): 

-

        credentials['stream_ids'] = stream_ids 

-

    utils.save_json_dict(CREDENTIALS_FILE, credentials) 

-

    ensure_local_plotly_files()  # make sure what we just put there is OK 

-

 

-

 

-

def get_credentials_file(*args): 

-

    """Return specified args from `~/.plotly_credentials`. as dict. 

-

 

-

    Returns all if no arguments are specified. 

-

 

-

    Example: 

-

        get_credentials_file('username') 

-

 

-

    """ 

-

    if _file_permissions: 

-

        ensure_local_plotly_files()  # make sure what's there is OK 

-

        return utils.load_json_dict(CREDENTIALS_FILE, *args) 

-

    else: 

-

        return _FILE_CONTENT[CREDENTIALS_FILE] 

-

 

-

 

-

def reset_credentials_file(): 

-

    ensure_local_plotly_files()  # make sure what's there is OK 

-

    f = open(CREDENTIALS_FILE, 'w') 

-

    f.close() 

-

    ensure_local_plotly_files()  # put the defaults back 

-

 

-

 

-

### config tools ### 

-

 

-

def set_config_file(plotly_domain=None, plotly_streaming_domain=None): 

-

    """Set the keyword-value pairs in `~/.plotly/.config`. 

-

 

-

    """ 

-

    if not _file_permissions: 

-

        raise exceptions.PlotlyError("You don't have proper file permissions " 

-

                                     "to run this function.") 

-

    ensure_local_plotly_files()  # make sure what's there is OK 

-

    settings = get_config_file() 

-

    if isinstance(plotly_domain, six.string_types): 

-

        settings['plotly_domain'] = plotly_domain 

-

    if isinstance(plotly_streaming_domain, six.string_types): 

-

        settings['plotly_streaming_domain'] = plotly_streaming_domain 

-

    utils.save_json_dict(CONFIG_FILE, settings) 

-

    ensure_local_plotly_files()  # make sure what we just put there is OK 

-

 

-

 

-

def get_config_file(*args): 

-

    """Return specified args from `~/.plotly_credentials`. as dict. 

-

 

-

    Returns all if no arguments are specified. 

-

 

-

    Example: 

-

        get_credentials_file('username') 

-

 

-

    """ 

-

    if _file_permissions: 

-

        ensure_local_plotly_files()  # make sure what's there is OK 

-

        return utils.load_json_dict(CONFIG_FILE, *args) 

-

    else: 

-

        return _FILE_CONTENT[CONFIG_FILE] 

-

 

-

 

-

def reset_config_file(): 

-

    ensure_local_plotly_files()  # make sure what's there is OK 

-

    f = open(CONFIG_FILE, 'w') 

-

    f.close() 

-

    ensure_local_plotly_files()  # put the defaults back 

-

 

-

 

-

### embed tools ### 

-

 

-

def get_embed(file_owner_or_url, file_id=None, width="100%", height=525): 

-

    """Returns HTML code to embed figure on a webpage as an <iframe> 

-

     

-

    Plotly uniquely identifies figures with a 'file_owner'/'file_id' pair. 

-

    Since each file is given a corresponding unique url, you may also simply 

-

    pass a valid plotly url as the first argument. 

-

 

-

    Note, if you're using a file_owner string as the first argument, you MUST 

-

    specify a `file_id` keyword argument. Else, if you're using a url string 

-

    as the first argument, you MUST NOT specify a `file_id` keyword argument, or 

-

    file_id must be set to Python's None value. 

-

 

-

    Positional arguments: 

-

    file_owner_or_url (string) -- a valid plotly username OR a valid plotly url 

-

 

-

    Keyword arguments: 

-

    file_id (default=None) -- an int or string that can be converted to int 

-

                              if you're using a url, don't fill this in! 

-

    width (default="100%") -- an int or string corresp. to width of the figure 

-

    height (default="525") -- same as width but corresp. to the height of the figure 

-

 

-

    """ 

-

    padding = 25 

-

    plotly_rest_url = get_config_file()['plotly_domain'] 

-

    if file_id is None:  # assume we're using a url 

-

        url = file_owner_or_url 

-

        if url[:len(plotly_rest_url)] != plotly_rest_url: 

-

            raise exceptions.PlotlyError( 

-

                "Because you didn't supply a 'file_id' in the call, " 

-

                "we're assuming you're trying to snag a figure from a url. " 

-

                "You supplied the url, '{}', we expected it to start with '{}'." 

-

                "\nRun help on this function for more information." 

-

                "".format(url, plotly_rest_url)) 

-

        head = plotly_rest_url + "/~" 

-

        file_owner = url.replace(head, "").split('/')[0] 

-

        file_id = url.replace(head, "").split('/')[1] 

-

    else: 

-

        file_owner = file_owner_or_url 

-

    resource = "/apigetfile/{file_owner}/{file_id}".format(file_owner=file_owner, 

-

                                                           file_id=file_id) 

-

    try: 

-

        test_if_int = int(file_id) 

-

    except ValueError: 

-

        raise exceptions.PlotlyError( 

-

            "The 'file_id' argument was not able to be converted into an " 

-

            "integer number. Make sure that the positional 'file_id' argument " 

-

            "is a number that can be converted into an integer or a string " 

-

            "that can be converted into an integer." 

-

        ) 

-

    if int(file_id) < 0: 

-

        raise exceptions.PlotlyError( 

-

            "The 'file_id' argument must be a non-negative number." 

-

        ) 

-

    if isinstance(width, int): 

-

        s = ("<iframe id=\"igraph\" scrolling=\"no\" style=\"border:none;\"" 

-

             "seamless=\"seamless\" " 

-

             "src=\"{plotly_rest_url}/" 

-

             "~{file_owner}/{file_id}/{plot_width}/{plot_height}\" " 

-

             "height=\"{iframe_height}\" width=\"{iframe_width}\">" 

-

             "</iframe>").format( 

-

            plotly_rest_url=plotly_rest_url, 

-

            file_owner=file_owner, file_id=file_id, 

-

            plot_width=width-padding, plot_height=height-padding, 

-

            iframe_height=height, iframe_width=width) 

-

    else: 

-

        s = ("<iframe id=\"igraph\" scrolling=\"no\" style=\"border:none;\"" 

-

             "seamless=\"seamless\" " 

-

             "src=\"{plotly_rest_url}/" 

-

             "~{file_owner}/{file_id}\" " 

-

             "height=\"{iframe_height}\" width=\"{iframe_width}\">" 

-

             "</iframe>").format( 

-

            plotly_rest_url=plotly_rest_url, 

-

            file_owner=file_owner, file_id=file_id, 

-

            iframe_height=height, iframe_width=width) 

-

 

-

    return s 

-

 

-

 

-

def embed(file_owner_or_url, file_id=None, width="100%", height=525): 

-

    """Embeds existing Plotly figure in IPython Notebook 

-

     

-

    Plotly uniquely identifies figures with a 'file_owner'/'file_id' pair. 

-

    Since each file is given a corresponding unique url, you may also simply 

-

    pass a valid plotly url as the first argument. 

-

 

-

    Note, if you're using a file_owner string as the first argument, you MUST 

-

    specify a `file_id` keyword argument. Else, if you're using a url string 

-

    as the first argument, you MUST NOT specify a `file_id` keyword argument, or 

-

    file_id must be set to Python's None value. 

-

 

-

    Positional arguments: 

-

    file_owner_or_url (string) -- a valid plotly username OR a valid plotly url 

-

 

-

    Keyword arguments: 

-

    file_id (default=None) -- an int or string that can be converted to int 

-

                              if you're using a url, don't fill this in! 

-

    width (default="100%") -- an int or string corresp. to width of the figure 

-

    height (default="525") -- same as width but corresp. to the height of the figure 

-

 

-

    """ 

-

    s = get_embed(file_owner_or_url, file_id, width, height) 

-

    try: 

-

        # see if we are in the SageMath Cloud 

-

        from sage_salvus import html 

-

        return html(s, hide=False) 

-

    except: 

-

        pass 

-

    try: 

-

        from IPython.display import HTML, display 

-

        display(HTML(s)) 

-

    except: 

-

        pass 

-

 

-

 

-

### mpl-related tools ### 

-

@utils.template_doc(**get_config_file()) 

-

def mpl_to_plotly(fig, resize=False, strip_style=False, verbose=False): 

-

    """Convert a matplotlib figure to plotly dictionary and send. 

-

 

-

    All available information about matplotlib visualizations are stored 

-

    within a matplotlib.figure.Figure object. You can create a plot in python 

-

    using matplotlib, store the figure object, and then pass this object to 

-

    the fig_to_plotly function. In the background, mplexporter is used to 

-

    crawl through the mpl figure object for appropriate information. This 

-

    information is then systematically sent to the PlotlyRenderer which 

-

    creates the JSON structure used to make plotly visualizations. Finally, 

-

    these dictionaries are sent to plotly and your browser should open up a 

-

    new tab for viewing! Optionally, if you're working in IPython, you can 

-

    set notebook=True and the PlotlyRenderer will call plotly.iplot instead 

-

    of plotly.plot to have the graph appear directly in the IPython notebook. 

-

 

-

    Note, this function gives the user access to a simple, one-line way to 

-

    render an mpl figure in plotly. If you need to trouble shoot, you can do 

-

    this step manually by NOT running this fuction and entereing the following: 

-

 

-

    ============================================================================ 

-

    from mplexporter import Exporter 

-

    from mplexporter.renderers import PlotlyRenderer 

-

 

-

    # create an mpl figure and store it under a varialble 'fig' 

-

 

-

    renderer = PlotlyRenderer() 

-

    exporter = Exporter(renderer) 

-

    exporter.run(fig) 

-

    ============================================================================ 

-

 

-

    You can then inspect the JSON structures by accessing these: 

-

 

-

    renderer.layout -- a plotly layout dictionary 

-

    renderer.data -- a list of plotly data dictionaries 

-

 

-

    Positional arguments: 

-

    fig -- a matplotlib figure object 

-

    username -- a valid plotly username ** 

-

    api_key -- a valid api_key for the above username ** 

-

    notebook -- an option for use with an IPython notebook 

-

 

-

    ** Don't have a username/api_key? Try looking here: 

-

    {plotly_domain}/plot 

-

 

-

    ** Forgot your api_key? Try signing in and looking here: 

-

    {plotly_domain}/api/python/getting-started 

-

 

-

    """ 

-

    if _matplotlylib_imported: 

-

        renderer = matplotlylib.PlotlyRenderer() 

-

        matplotlylib.Exporter(renderer).run(fig) 

-

        if resize: 

-

            renderer.resize() 

-

        if strip_style: 

-

            renderer.strip_style() 

-

        if verbose: 

-

            print(renderer.msg) 

-

        return renderer.plotly_fig 

-

    else: 

-

        warnings.warn( 

-

            "To use Plotly's matplotlylib functionality, you'll need to have " 

-

            "matplotlib successfully installed with all of its dependencies. " 

-

            "You're getting this error because matplotlib or one of its " 

-

            "dependencies doesn't seem to be installed correctly.") 

-

 

-

 

-

### graph_objs related tools ### 

-

 

-

# TODO: Scale spacing based on number of plots and figure size 

-

def get_subplots(rows=1, columns=1, horizontal_spacing=0.1, 

-

                 vertical_spacing=0.15, print_grid=False): 

-

    """Return a dictionary instance with the subplots set in 'layout'. 

-

 

-

    Example 1: 

-

        # stack two subplots vertically 

-

        fig = tools.get_subplots(rows=2) 

-

        fig['data'] += [Scatter(x=[1,2,3], y=[2,1,2], xaxis='x1', yaxis='y1')] 

-

        fig['data'] += [Scatter(x=[1,2,3], y=[2,1,2], xaxis='x2', yaxis='y2')] 

-

 

-

    Example 2: 

-

        # print out string showing the subplot grid you've put in the layout 

-

        fig = tools.get_subplots(rows=3, columns=2, print_grid=True) 

-

 

-

    key (types, default=default): 

-

        description. 

-

 

-

    rows (int, default=1): 

-

        Number of rows, evenly spaced vertically on the figure. 

-

 

-

    columns (int, default=1): 

-

        Number of columns, evenly spaced horizontally on the figure. 

-

 

-

    horizontal_spacing (float in [0,1], default=0.1): 

-

        Space between subplot columns. Applied to all columns. 

-

 

-

    vertical_spacing (float in [0,1], default=0.05): 

-

        Space between subplot rows. Applied to all rows. 

-

 

-

    print_grid (True | False, default=False): 

-

        If True, prints a tab-delimited string representation of your plot grid. 

-

 

-

    """ 

-

    fig = dict(layout=graph_objs.Layout())  # will return this at the end 

-

    plot_width = (1 - horizontal_spacing * (columns - 1)) / columns 

-

    plot_height = (1 - vertical_spacing * (rows - 1)) / rows 

-

    plot_num = 0 

-

    for rrr in range(rows): 

-

        for ccc in range(columns): 

-

            xaxis_name = 'xaxis{}'.format(plot_num + 1) 

-

            x_anchor = 'y{}'.format(plot_num + 1) 

-

            x_start = (plot_width + horizontal_spacing) * ccc 

-

            x_end = x_start + plot_width 

-

 

-

            yaxis_name = 'yaxis{}'.format(plot_num + 1) 

-

            y_anchor = 'x{}'.format(plot_num + 1) 

-

            y_start = (plot_height + vertical_spacing) * rrr 

-

            y_end = y_start + plot_height 

-

 

-

            xaxis = graph_objs.XAxis(domain=[x_start, x_end], anchor=x_anchor) 

-

            fig['layout'][xaxis_name] = xaxis 

-

            yaxis = graph_objs.YAxis(domain=[y_start, y_end], anchor=y_anchor) 

-

            fig['layout'][yaxis_name] = yaxis 

-

            plot_num += 1 

-

    if print_grid: 

-

        print("This is the format of your plot grid!") 

-

        grid_string = "" 

-

        plot = 1 

-

        for rrr in range(rows): 

-

            grid_line = "" 

-

            for ccc in range(columns): 

-

                grid_line += "[{}]\t".format(plot) 

-

                plot += 1 

-

            grid_string = grid_line + '\n' + grid_string 

-

        print(grid_string) 

-

    return graph_objs.Figure(fig)  # forces us to validate what we just did... 

-

 

-

 

-

def get_valid_graph_obj(obj, obj_type=None): 

-

    """Returns a new graph object that is guaranteed to pass validate(). 

-

 

-

    CAREFUL: this will *silently* strip out invalid pieces of the object. 

-

 

-

    """ 

-

    try: 

-

        new_obj = graph_objs.NAME_TO_CLASS[obj.__class__.__name__]() 

-

    except KeyError: 

-

        try: 

-

            new_obj = graph_objs.NAME_TO_CLASS[obj_type]() 

-

        except KeyError: 

-

            raise exceptions.PlotlyError( 

-

                "'{}' nor '{}' are recognizable graph_objs.". 

-

                format(obj.__class__.__name__, obj_type)) 

-

    if isinstance(new_obj, list): 

-

        new_obj += obj 

-

    else: 

-

        for key, val in list(obj.items()): 

-

            new_obj[key] = val 

-

    new_obj.force_clean() 

-

    return new_obj 

-

 

-

 

-

def validate(obj, obj_type): 

-

    """Validate a dictionary, list, or graph object as 'obj_type'. 

-

 

-

    This will not alter the 'obj' referenced in the call signature. It will 

-

    raise an error if the 'obj' reference could not be instantiated as a 

-

    valid 'obj_type' graph object. 

-

 

-

    """ 

-

    try: 

-

        obj_type = graph_objs.KEY_TO_NAME[obj_type] 

-

    except KeyError: 

-

        pass 

-

    try: 

-

        test_obj = graph_objs.NAME_TO_CLASS[obj_type](obj) 

-

    except KeyError: 

-

        raise exceptions.PlotlyError( 

-

            "'{}' is not a recognizable graph_obj.". 

-

            format(obj_type)) 

-

 

-

 

-

def validate_stream(obj, obj_type): 

-

    """Validate a data dictionary (only) for use with streaming. 

-

 

-

    An error is raised if a key within (or nested within) is not streamable. 

-

 

-

    """ 

-

    try: 

-

        obj_type = graph_objs.KEY_TO_NAME[obj_type] 

-

    except KeyError: 

-

        pass 

-

    info = graph_objs.INFO[graph_objs.NAME_TO_KEY[obj_type]] 

-

    for key, val in list(obj.items()): 

-

        if key == 'type': 

-

            continue 

-

        if 'streamable' in info[key]: 

-

            if not info[key]['streamable']: 

-

                raise exceptions.PlotlyError( 

-

                    "The '{}' key is not streamable in the '{}' object".format( 

-

                        key, obj_type 

-

                    ) 

-

                ) 

-

        else: 

-

            raise exceptions.PlotlyError( 

-

                "The '{}' key is not streamable in the '{}' object".format( 

-

                    key, obj_type 

-

                ) 

-

            ) 

-

        try: 

-

            sub_obj_type = graph_objs.KEY_TO_NAME[key] 

-

            validate_stream(val, sub_obj_type) 

-

        except KeyError: 

-

            pass 

-

 

-

 

-

def _replace_newline(obj): 

-

    """Replaces '\n' with '<br>' for all strings in a collection.""" 

-

    if isinstance(obj, dict): 

-

        d = dict() 

-

        for key, val in list(obj.items()): 

-

            d[key] = _replace_newline(val) 

-

        return d 

-

    elif isinstance(obj, list): 

-

        l = list() 

-

        for index, entry in enumerate(obj): 

-

            l += [_replace_newline(entry)] 

-

        return l 

-

    elif isinstance(obj, six.string_types): 

-

        s = obj.replace('\n', '<br>') 

-

        if s != obj: 

-

            warnings.warn("Looks like you used a newline character: '\\n'.\n\n" 

-

                          "Plotly uses a subset of HTML escape characters\n" 

-

                          "to do things like newline (<br>), bold (<b></b>),\n" 

-

                          "italics (<i></i>), etc. Your newline characters \n" 

-

                          "have been converted to '<br>' so they will show \n" 

-

                          "up right on your Plotly figure!") 

-

        return s 

-

    else: 

-

        return obj  # we return the actual reference... but DON'T mutate. 

- -
-
- - - - - diff --git a/plotly/tests/coverage/plotly_utils.html b/plotly/tests/coverage/plotly_utils.html deleted file mode 100644 index 62b0a6bcccc..00000000000 --- a/plotly/tests/coverage/plotly_utils.html +++ /dev/null @@ -1,382 +0,0 @@ - - - - - - - - Coverage for plotly/utils: 42% - - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

-

27

-

28

-

29

-

30

-

31

-

32

-

33

-

34

-

35

-

36

-

37

-

38

-

39

-

40

-

41

-

42

-

43

-

44

-

45

-

46

-

47

-

48

-

49

-

50

-

51

-

52

-

53

-

54

-

55

-

56

-

57

-

58

-

59

-

60

-

61

-

62

-

63

-

64

-

65

-

66

-

67

-

68

-

69

-

70

-

71

-

72

-

73

-

74

-

75

-

76

-

77

-

78

-

79

-

80

-

81

-

82

-

83

-

84

-

85

-

86

-

87

-

88

-

89

-

90

-

91

-

92

-

93

-

94

-

95

-

96

-

97

-

98

-

99

-

100

-

101

-

102

-

103

-

104

-

105

-

106

-

107

-

108

-

109

-

110

-

111

-

112

-

113

-

114

-

115

-

116

-

117

-

118

-

119

-

120

-

121

-

122

-

123

-

124

-

125

-

126

-

127

-

128

-

129

-

130

-

131

-

132

-

133

-

134

-

135

-

136

-

137

-

138

-

139

-

140

-

141

-

142

-

143

-

144

-

145

-

146

-

147

-

148

-

149

-

150

- -
-

""" 

-

utils 

-

===== 

-

 

-

Low-level functionality NOT intended for users to EVER use. 

-

 

-

""" 

-

 

-

import json 

-

import os.path 

-

import sys 

-

 

-

 

-

### general file setup tools ### 

-

 

-

def load_json_dict(filename, *args): 

-

    """Checks if file exists. Returns {} if something fails.""" 

-

    data = {} 

-

    if os.path.exists(filename): 

-

        with open(filename, "r") as f: 

-

            try: 

-

                data = json.load(f) 

-

                if not isinstance(data, dict): 

-

                    data = {} 

-

            except: 

-

                pass # TODO: issue a warning and bubble it up 

-

        if args: 

-

            d = dict() 

-

            for key in args: 

-

                if key in data: 

-

                    d[key] = data[key] 

-

            return d 

-

            # TODO: replace with below if we drop Python 2.6 compatibility 

-

            # return {key: data[key] for key in args if key in data} 

-

    return data 

-

 

-

 

-

def save_json_dict(filename, json_dict): 

-

    """Will error if filename is not appropriate, but it's checked elsewhere. 

-

    """ 

-

    if isinstance(json_dict, dict): 

-

        with open(filename, "w") as f: 

-

            f.write(json.dumps(json_dict, indent=4)) 

-

    else: 

-

        raise TypeError("json_dict was not a dictionay. couldn't save.") 

-

 

-

 

-

### Custom JSON encoders ### 

-

class _plotlyJSONEncoder(json.JSONEncoder): 

-

    def numpyJSONEncoder(self, obj): 

-

        try: 

-

            import numpy 

-

            if type(obj).__module__.split('.')[0] == numpy.__name__: 

-

                l = obj.tolist() 

-

                d = self.datetimeJSONEncoder(l) 

-

                return d if d is not None else l 

-

        except: 

-

            pass 

-

        return None 

-

 

-

    def datetimeJSONEncoder(self, obj): 

-

        # if datetime or iterable of datetimes, convert to a string that plotly understands 

-

        # format as %Y-%m-%d %H:%M:%S.%f, %Y-%m-%d %H:%M:%S, or %Y-%m-%d depending on what non-zero resolution was provided 

-

        import datetime 

-

        try: 

-

            if isinstance(obj, (datetime.datetime, datetime.date)): 

-

                if obj.microsecond != 0: 

-

                    return obj.strftime('%Y-%m-%d %H:%M:%S.%f') 

-

                elif obj.second != 0 or obj.minute != 0 or obj.hour != 0: 

-

                    return obj.strftime('%Y-%m-%d %H:%M:%S') 

-

                else: 

-

                    return obj.strftime('%Y-%m-%d') 

-

            elif isinstance(obj[0], (datetime.datetime, datetime.date)): 

-

                return [o.strftime( 

-

                        '%Y-%m-%d %H:%M:%S.%f') if o.microsecond != 0 else 

-

                        o.strftime('%Y-%m-%d %H:%M:%S') if o.second != 0 or o.minute != 0 or o.hour != 0 else 

-

                        o.strftime('%Y-%m-%d') 

-

                        for o in obj] 

-

        except: 

-

            pass 

-

        return None 

-

 

-

    def pandasJSONEncoder(self, obj): 

-

        try: 

-

            import pandas 

-

            if isinstance(obj, pandas.Series): 

-

                return obj.tolist() 

-

        except: 

-

            pass 

-

        return None 

-

 

-

    def sageJSONEncoder(self, obj): 

-

        try: 

-

            from sage.all import RR, ZZ 

-

            if obj in RR: 

-

                return float(obj) 

-

            elif obj in ZZ: 

-

                return int(obj) 

-

        except: 

-

            pass 

-

        return None 

-

 

-

    def default(self, obj): 

-

        try: 

-

            return json.dumps(obj) 

-

        except TypeError as e: 

-

            encoders = (self.datetimeJSONEncoder, self.numpyJSONEncoder, 

-

                        self.pandasJSONEncoder, self.sageJSONEncoder) 

-

            for encoder in encoders: 

-

                s = encoder(obj) 

-

                if s is not None: 

-

                    return s 

-

            raise e 

-

        return json.JSONEncoder.default(self, obj) 

-

 

-

 

-

### unicode stuff ### 

-

def decode_unicode(coll): 

-

    if isinstance(coll, list): 

-

        for no, entry in enumerate(coll): 

-

            if isinstance(entry, (dict, list)): 

-

                coll[no] = decode_unicode(entry) 

-

            else: 

-

                if isinstance(entry, str): 

-

                    try: 

-

                        coll[no] = str(entry) 

-

                    except UnicodeEncodeError: 

-

                        pass 

-

    elif isinstance(coll, dict): 

-

        keys, vals = list(coll.keys()), list(coll.values()) 

-

        for key, val in zip(keys, vals): 

-

            if isinstance(val, (dict, list)): 

-

                coll[key] = decode_unicode(val) 

-

            elif isinstance(val, str): 

-

                try: 

-

                    coll[key] = str(val) 

-

                except UnicodeEncodeError: 

-

                    pass 

-

            coll[str(key)] = coll.pop(key) 

-

    return coll 

-

 

-

 

-

### docstring templating ### 

-

def template_doc(**names): 

-

    def _decorator(func): 

-

        if sys.version[:3] != '3.2': 

-

            if func.__doc__ is not None: 

-

                func.__doc__ = func.__doc__.format(**names) 

-

        return func 

-

    return _decorator 

- -
-
- - - - - diff --git a/plotly/tests/coverage/plotly_version.html b/plotly/tests/coverage/plotly_version.html deleted file mode 100644 index 6b3c192b7f5..00000000000 --- a/plotly/tests/coverage/plotly_version.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - Coverage for plotly/version: 100% - - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

- -
-

__version__ = '1.2.0' 

- -
-
- - - - - diff --git a/plotly/tests/coverage/status.dat b/plotly/tests/coverage/status.dat deleted file mode 100644 index ad3aa4ecb98..00000000000 --- a/plotly/tests/coverage/status.dat +++ /dev/null @@ -1,340 +0,0 @@ -(dp1 -S'files' -p2 -(dp3 -S'plotly_matplotlylib_mpltools' -p4 -(dp5 -S'index' -p6 -(dp7 -S'html_filename' -p8 -S'plotly_matplotlylib_mpltools.html' -p9 -sS'name' -p10 -S'plotly/matplotlylib/mpltools' -p11 -sS'nums' -p12 -ccopy_reg -_reconstructor -p13 -(ccoverage.results -Numbers -p14 -c__builtin__ -object -p15 -NtRp16 -(dp17 -S'n_files' -p18 -I1 -sS'n_branches' -p19 -I0 -sS'n_statements' -p20 -I217 -sS'n_excluded' -p21 -I0 -sS'n_partial_branches' -p22 -I0 -sS'n_missing' -p23 -I47 -sS'n_missing_branches' -p24 -I0 -sbssS'hash' -p25 -S'\x00\xfeY]\xb8u\xfd\x9a#bi\x1e\xb4\xcb<\x1c' -p26 -ssS'plotly_exceptions' -p27 -(dp28 -g6 -(dp29 -g8 -S'plotly_exceptions.html' -p30 -sg10 -S'plotly/exceptions' -p31 -sg12 -g13 -(g14 -g15 -NtRp32 -(dp33 -g18 -I1 -sg19 -I0 -sg20 -I75 -sg21 -I0 -sg22 -I0 -sg23 -I7 -sg24 -I0 -sbssg25 -S'\xeau~(G\xecc\xba\xf7\x9e.\xf6F\xc4"G' -p34 -ssS'plotly_matplotlylib_renderer' -p35 -(dp36 -g6 -(dp37 -g8 -S'plotly_matplotlylib_renderer.html' -p38 -sg10 -S'plotly/matplotlylib/renderer' -p39 -sg12 -g13 -(g14 -g15 -NtRp40 -(dp41 -g18 -I1 -sg19 -I0 -sg20 -I217 -sg21 -I0 -sg22 -I0 -sg23 -I59 -sg24 -I0 -sbssg25 -S'\xd9f=\x92sE\xc7b\x8b@\xa8\xb3\xfe\x7f\xd7\xfc' -p42 -ssS'plotly_tools' -p43 -(dp44 -g6 -(dp45 -g8 -S'plotly_tools.html' -p46 -sg10 -S'plotly/tools' -p47 -sg12 -g13 -(g14 -g15 -NtRp48 -(dp49 -g18 -I1 -sg19 -I0 -sg20 -I233 -sg21 -I0 -sg22 -I0 -sg23 -I51 -sg24 -I0 -sbssg25 -S"\x14\xc4\xb6\x1e\xf2\xa2l\x13\tfG\x97j%'\x0f" -p50 -ssS'plotly_graph_objs_graph_objs' -p51 -(dp52 -g6 -(dp53 -g8 -S'plotly_graph_objs_graph_objs.html' -p54 -sg10 -S'plotly/graph_objs/graph_objs' -p55 -sg12 -g13 -(g14 -g15 -NtRp56 -(dp57 -g18 -I1 -sg19 -I0 -sg20 -I581 -sg21 -I0 -sg22 -I0 -sg23 -I63 -sg24 -I0 -sbssg25 -S'\xd9\xc9\xc1\x8a\xb7|W\xdf\x9b\xab\xb1\xfb@p\xb3\xeb' -p58 -ssS'plotly_utils' -p59 -(dp60 -g6 -(dp61 -g8 -S'plotly_utils.html' -p62 -sg10 -S'plotly/utils' -p63 -sg12 -g13 -(g14 -g15 -NtRp64 -(dp65 -g18 -I1 -sg19 -I0 -sg20 -I108 -sg21 -I0 -sg22 -I0 -sg23 -I63 -sg24 -I0 -sbssg25 -S'\x16\xdd\x19\xcf5\x94\x06\x82\x1f\xd6\x8f\x84\xd9\x0fN\xe2' -p66 -ssS'plotly_graph_objs_graph_objs_tools' -p67 -(dp68 -g6 -(dp69 -g8 -S'plotly_graph_objs_graph_objs_tools.html' -p70 -sg10 -S'plotly/graph_objs/graph_objs_tools' -p71 -sg12 -g13 -(g14 -g15 -NtRp72 -(dp73 -g18 -I1 -sg19 -I0 -sg20 -I8 -sg21 -I0 -sg22 -I0 -sg23 -I1 -sg24 -I0 -sbssg25 -S"UV7\xa0\xd2\x1d\x12'\x11\x97\x18\xf1^\x9btq" -p74 -ssS'plotly_version' -p75 -(dp76 -g6 -(dp77 -g8 -S'plotly_version.html' -p78 -sg10 -S'plotly/version' -p79 -sg12 -g13 -(g14 -g15 -NtRp80 -(dp81 -g18 -I1 -sg19 -I0 -sg20 -I1 -sg21 -I0 -sg22 -I0 -sg23 -I0 -sg24 -I0 -sbssg25 -S'~\x01\xf2\xef\xb4kKiMW\xebZ\xc1 \xa6.' -p82 -ssS'plotly_plotly_plotly' -p83 -(dp84 -g6 -(dp85 -g8 -S'plotly_plotly_plotly.html' -p86 -sg10 -S'plotly/plotly/plotly' -p87 -sg12 -g13 -(g14 -g15 -NtRp88 -(dp89 -g18 -I1 -sg19 -I0 -sg20 -I270 -sg21 -I0 -sg22 -I0 -sg23 -I104 -sg24 -I0 -sbssg25 -S'\xa9"\x99\x0fQ\xae\xdbO\xd4\x06\xcd\xb9S\x0f\xae\xb9' -p90 -sssS'version' -p91 -S'3.7.1' -p92 -sS'settings' -p93 -S'\r\xf7\r\xc2\n\xea2\xb2\x8fLm\xbb\xd0\xda\xf7\x12' -p94 -sS'format' -p95 -I1 -s. \ No newline at end of file diff --git a/plotly/tests/coverage/style.css b/plotly/tests/coverage/style.css deleted file mode 100644 index 811c64019c0..00000000000 --- a/plotly/tests/coverage/style.css +++ /dev/null @@ -1,300 +0,0 @@ -/* CSS styles for Coverage. */ -/* Page-wide styles */ -html, body, h1, h2, h3, p, td, th { - margin: 0; - padding: 0; - border: 0; - outline: 0; - font-weight: inherit; - font-style: inherit; - font-size: 100%; - font-family: inherit; - vertical-align: baseline; - } - -/* Set baseline grid to 16 pt. */ -body { - font-family: georgia, serif; - font-size: 1em; - } - -html>body { - font-size: 16px; - } - -/* Set base font size to 12/16 */ -p { - font-size: .75em; /* 12/16 */ - line-height: 1.33333333em; /* 16/12 */ - } - -table { - border-collapse: collapse; - } - -a.nav { - text-decoration: none; - color: inherit; - } -a.nav:hover { - text-decoration: underline; - color: inherit; - } - -/* Page structure */ -#header { - background: #f8f8f8; - width: 100%; - border-bottom: 1px solid #eee; - } - -#source { - padding: 1em; - font-family: "courier new", monospace; - } - -#indexfile #footer { - margin: 1em 3em; - } - -#pyfile #footer { - margin: 1em 1em; - } - -#footer .content { - padding: 0; - font-size: 85%; - font-family: verdana, sans-serif; - color: #666666; - font-style: italic; - } - -#index { - margin: 1em 0 0 3em; - } - -/* Header styles */ -#header .content { - padding: 1em 3em; - } - -h1 { - font-size: 1.25em; -} - -h2.stats { - margin-top: .5em; - font-size: 1em; -} -.stats span { - border: 1px solid; - padding: .1em .25em; - margin: 0 .1em; - cursor: pointer; - border-color: #999 #ccc #ccc #999; -} -.stats span.hide_run, .stats span.hide_exc, -.stats span.hide_mis, .stats span.hide_par, -.stats span.par.hide_run.hide_par { - border-color: #ccc #999 #999 #ccc; -} -.stats span.par.hide_run { - border-color: #999 #ccc #ccc #999; -} - -.stats span.run { - background: #ddffdd; -} -.stats span.exc { - background: #eeeeee; -} -.stats span.mis { - background: #ffdddd; -} -.stats span.hide_run { - background: #eeffee; -} -.stats span.hide_exc { - background: #f5f5f5; -} -.stats span.hide_mis { - background: #ffeeee; -} -.stats span.par { - background: #ffffaa; -} -.stats span.hide_par { - background: #ffffcc; -} - -/* Help panel */ -#keyboard_icon { - float: right; - cursor: pointer; -} - -.help_panel { - position: absolute; - background: #ffc; - padding: .5em; - border: 1px solid #883; - display: none; -} - -#indexfile .help_panel { - width: 20em; height: 4em; -} - -#pyfile .help_panel { - width: 16em; height: 8em; -} - -.help_panel .legend { - font-style: italic; - margin-bottom: 1em; -} - -#panel_icon { - float: right; - cursor: pointer; -} - -.keyhelp { - margin: .75em; -} - -.keyhelp .key { - border: 1px solid black; - border-color: #888 #333 #333 #888; - padding: .1em .35em; - font-family: monospace; - font-weight: bold; - background: #eee; -} - -/* Source file styles */ -.linenos p { - text-align: right; - margin: 0; - padding: 0 .5em; - color: #999999; - font-family: verdana, sans-serif; - font-size: .625em; /* 10/16 */ - line-height: 1.6em; /* 16/10 */ - } -.linenos p.highlight { - background: #ffdd00; - } -.linenos p a { - text-decoration: none; - color: #999999; - } -.linenos p a:hover { - text-decoration: underline; - color: #999999; - } - -td.text { - width: 100%; - } -.text p { - margin: 0; - padding: 0 0 0 .5em; - border-left: 2px solid #ffffff; - white-space: nowrap; - } - -.text p.mis { - background: #ffdddd; - border-left: 2px solid #ff0000; - } -.text p.run, .text p.run.hide_par { - background: #ddffdd; - border-left: 2px solid #00ff00; - } -.text p.exc { - background: #eeeeee; - border-left: 2px solid #808080; - } -.text p.par, .text p.par.hide_run { - background: #ffffaa; - border-left: 2px solid #eeee99; - } -.text p.hide_run, .text p.hide_exc, .text p.hide_mis, .text p.hide_par, -.text p.hide_run.hide_par { - background: inherit; - } - -.text span.annotate { - font-family: georgia; - font-style: italic; - color: #666; - float: right; - padding-right: .5em; - } -.text p.hide_par span.annotate { - display: none; - } - -/* Syntax coloring */ -.text .com { - color: green; - font-style: italic; - line-height: 1px; - } -.text .key { - font-weight: bold; - line-height: 1px; - } -.text .str { - color: #000080; - } - -/* index styles */ -#index td, #index th { - text-align: right; - width: 5em; - padding: .25em .5em; - border-bottom: 1px solid #eee; - } -#index th { - font-style: italic; - color: #333; - border-bottom: 1px solid #ccc; - cursor: pointer; - } -#index th:hover { - background: #eee; - border-bottom: 1px solid #999; - } -#index td.left, #index th.left { - padding-left: 0; - } -#index td.right, #index th.right { - padding-right: 0; - } -#index th.headerSortDown, #index th.headerSortUp { - border-bottom: 1px solid #000; - } -#index td.name, #index th.name { - text-align: left; - width: auto; - } -#index td.name a { - text-decoration: none; - color: #000; - } -#index td.name a:hover { - text-decoration: underline; - color: #000; - } -#index tr.total { - } -#index tr.total td { - font-weight: bold; - border-top: 1px solid #ccc; - border-bottom: none; - } -#index tr.file:hover { - background: #eeeeee; - }