diff --git a/404.html b/404.html new file mode 100644 index 0000000..15477dc --- /dev/null +++ b/404.html @@ -0,0 +1,324 @@ + + + + + + + + + + + + + + + + + + viv + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ +

404 - Not found

+ +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 0000000..1cf13b9 Binary files /dev/null and b/assets/images/favicon.png differ diff --git a/assets/javascripts/bundle.b4d07000.min.js b/assets/javascripts/bundle.b4d07000.min.js new file mode 100644 index 0000000..3c0bdad --- /dev/null +++ b/assets/javascripts/bundle.b4d07000.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var Ci=Object.create;var gr=Object.defineProperty;var Ri=Object.getOwnPropertyDescriptor;var ki=Object.getOwnPropertyNames,Ht=Object.getOwnPropertySymbols,Hi=Object.getPrototypeOf,yr=Object.prototype.hasOwnProperty,nn=Object.prototype.propertyIsEnumerable;var rn=(e,t,r)=>t in e?gr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,P=(e,t)=>{for(var r in t||(t={}))yr.call(t,r)&&rn(e,r,t[r]);if(Ht)for(var r of Ht(t))nn.call(t,r)&&rn(e,r,t[r]);return e};var on=(e,t)=>{var r={};for(var n in e)yr.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(e!=null&&Ht)for(var n of Ht(e))t.indexOf(n)<0&&nn.call(e,n)&&(r[n]=e[n]);return r};var Pt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Pi=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of ki(t))!yr.call(e,o)&&o!==r&&gr(e,o,{get:()=>t[o],enumerable:!(n=Ri(t,o))||n.enumerable});return e};var yt=(e,t,r)=>(r=e!=null?Ci(Hi(e)):{},Pi(t||!e||!e.__esModule?gr(r,"default",{value:e,enumerable:!0}):r,e));var sn=Pt((xr,an)=>{(function(e,t){typeof xr=="object"&&typeof an!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(xr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,s={text:!0,search:!0,url:!0,tel:!0,email:!0,password:!0,number:!0,date:!0,month:!0,week:!0,time:!0,datetime:!0,"datetime-local":!0};function a(O){return!!(O&&O!==document&&O.nodeName!=="HTML"&&O.nodeName!=="BODY"&&"classList"in O&&"contains"in O.classList)}function f(O){var Qe=O.type,De=O.tagName;return!!(De==="INPUT"&&s[Qe]&&!O.readOnly||De==="TEXTAREA"&&!O.readOnly||O.isContentEditable)}function c(O){O.classList.contains("focus-visible")||(O.classList.add("focus-visible"),O.setAttribute("data-focus-visible-added",""))}function u(O){O.hasAttribute("data-focus-visible-added")&&(O.classList.remove("focus-visible"),O.removeAttribute("data-focus-visible-added"))}function p(O){O.metaKey||O.altKey||O.ctrlKey||(a(r.activeElement)&&c(r.activeElement),n=!0)}function m(O){n=!1}function d(O){a(O.target)&&(n||f(O.target))&&c(O.target)}function h(O){a(O.target)&&(O.target.classList.contains("focus-visible")||O.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(O.target))}function v(O){document.visibilityState==="hidden"&&(o&&(n=!0),Y())}function Y(){document.addEventListener("mousemove",N),document.addEventListener("mousedown",N),document.addEventListener("mouseup",N),document.addEventListener("pointermove",N),document.addEventListener("pointerdown",N),document.addEventListener("pointerup",N),document.addEventListener("touchmove",N),document.addEventListener("touchstart",N),document.addEventListener("touchend",N)}function B(){document.removeEventListener("mousemove",N),document.removeEventListener("mousedown",N),document.removeEventListener("mouseup",N),document.removeEventListener("pointermove",N),document.removeEventListener("pointerdown",N),document.removeEventListener("pointerup",N),document.removeEventListener("touchmove",N),document.removeEventListener("touchstart",N),document.removeEventListener("touchend",N)}function N(O){O.target.nodeName&&O.target.nodeName.toLowerCase()==="html"||(n=!1,B())}document.addEventListener("keydown",p,!0),document.addEventListener("mousedown",m,!0),document.addEventListener("pointerdown",m,!0),document.addEventListener("touchstart",m,!0),document.addEventListener("visibilitychange",v,!0),Y(),r.addEventListener("focus",d,!0),r.addEventListener("blur",h,!0),r.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&r.host?r.host.setAttribute("data-js-focus-visible",""):r.nodeType===Node.DOCUMENT_NODE&&(document.documentElement.classList.add("js-focus-visible"),document.documentElement.setAttribute("data-js-focus-visible",""))}if(typeof window!="undefined"&&typeof document!="undefined"){window.applyFocusVisiblePolyfill=e;var t;try{t=new CustomEvent("focus-visible-polyfill-ready")}catch(r){t=document.createEvent("CustomEvent"),t.initCustomEvent("focus-visible-polyfill-ready",!1,!1,{})}window.dispatchEvent(t)}typeof document!="undefined"&&e(document)})});var cn=Pt(Er=>{(function(e){var t=function(){try{return!!Symbol.iterator}catch(c){return!1}},r=t(),n=function(c){var u={next:function(){var p=c.shift();return{done:p===void 0,value:p}}};return r&&(u[Symbol.iterator]=function(){return u}),u},o=function(c){return encodeURIComponent(c).replace(/%20/g,"+")},i=function(c){return decodeURIComponent(String(c).replace(/\+/g," "))},s=function(){var c=function(p){Object.defineProperty(this,"_entries",{writable:!0,value:{}});var m=typeof p;if(m!=="undefined")if(m==="string")p!==""&&this._fromString(p);else if(p instanceof c){var d=this;p.forEach(function(B,N){d.append(N,B)})}else if(p!==null&&m==="object")if(Object.prototype.toString.call(p)==="[object Array]")for(var h=0;hd[0]?1:0}),c._entries&&(c._entries={});for(var p=0;p1?i(d[1]):"")}})})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Er);(function(e){var t=function(){try{var o=new e.URL("b","http://a");return o.pathname="c d",o.href==="http://a/c%20d"&&o.searchParams}catch(i){return!1}},r=function(){var o=e.URL,i=function(f,c){typeof f!="string"&&(f=String(f)),c&&typeof c!="string"&&(c=String(c));var u=document,p;if(c&&(e.location===void 0||c!==e.location.href)){c=c.toLowerCase(),u=document.implementation.createHTMLDocument(""),p=u.createElement("base"),p.href=c,u.head.appendChild(p);try{if(p.href.indexOf(c)!==0)throw new Error(p.href)}catch(O){throw new Error("URL unable to set base "+c+" due to "+O)}}var m=u.createElement("a");m.href=f,p&&(u.body.appendChild(m),m.href=m.href);var d=u.createElement("input");if(d.type="url",d.value=f,m.protocol===":"||!/:/.test(m.href)||!d.checkValidity()&&!c)throw new TypeError("Invalid URL");Object.defineProperty(this,"_anchorElement",{value:m});var h=new e.URLSearchParams(this.search),v=!0,Y=!0,B=this;["append","delete","set"].forEach(function(O){var Qe=h[O];h[O]=function(){Qe.apply(h,arguments),v&&(Y=!1,B.search=h.toString(),Y=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var N=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==N&&(N=this.search,Y&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},s=i.prototype,a=function(f){Object.defineProperty(s,f,{get:function(){return this._anchorElement[f]},set:function(c){this._anchorElement[f]=c},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(f){a(f)}),Object.defineProperty(s,"search",{get:function(){return this._anchorElement.search},set:function(f){this._anchorElement.search=f,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(s,{toString:{get:function(){var f=this;return function(){return f.href}}},href:{get:function(){return this._anchorElement.href.replace(/\?$/,"")},set:function(f){this._anchorElement.href=f,this._updateSearchParams()},enumerable:!0},pathname:{get:function(){return this._anchorElement.pathname.replace(/(^\/?)/,"/")},set:function(f){this._anchorElement.pathname=f},enumerable:!0},origin:{get:function(){var f={"http:":80,"https:":443,"ftp:":21}[this._anchorElement.protocol],c=this._anchorElement.port!=f&&this._anchorElement.port!=="";return this._anchorElement.protocol+"//"+this._anchorElement.hostname+(c?":"+this._anchorElement.port:"")},enumerable:!0},password:{get:function(){return""},set:function(f){},enumerable:!0},username:{get:function(){return""},set:function(f){},enumerable:!0}}),i.createObjectURL=function(f){return o.createObjectURL.apply(o,arguments)},i.revokeObjectURL=function(f){return o.revokeObjectURL.apply(o,arguments)},e.URL=i};if(t()||r(),e.location!==void 0&&!("origin"in e.location)){var n=function(){return e.location.protocol+"//"+e.location.hostname+(e.location.port?":"+e.location.port:"")};try{Object.defineProperty(e.location,"origin",{get:n,enumerable:!0})}catch(o){setInterval(function(){e.location.origin=n()},100)}}})(typeof global!="undefined"?global:typeof window!="undefined"?window:typeof self!="undefined"?self:Er)});var qr=Pt((Mt,Nr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Mt=="object"&&typeof Nr=="object"?Nr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Mt=="object"?Mt.ClipboardJS=r():t.ClipboardJS=r()})(Mt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return Ai}});var s=i(279),a=i.n(s),f=i(370),c=i.n(f),u=i(817),p=i.n(u);function m(j){try{return document.execCommand(j)}catch(T){return!1}}var d=function(T){var E=p()(T);return m("cut"),E},h=d;function v(j){var T=document.documentElement.getAttribute("dir")==="rtl",E=document.createElement("textarea");E.style.fontSize="12pt",E.style.border="0",E.style.padding="0",E.style.margin="0",E.style.position="absolute",E.style[T?"right":"left"]="-9999px";var H=window.pageYOffset||document.documentElement.scrollTop;return E.style.top="".concat(H,"px"),E.setAttribute("readonly",""),E.value=j,E}var Y=function(T,E){var H=v(T);E.container.appendChild(H);var I=p()(H);return m("copy"),H.remove(),I},B=function(T){var E=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},H="";return typeof T=="string"?H=Y(T,E):T instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(T==null?void 0:T.type)?H=Y(T.value,E):(H=p()(T),m("copy")),H},N=B;function O(j){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?O=function(E){return typeof E}:O=function(E){return E&&typeof Symbol=="function"&&E.constructor===Symbol&&E!==Symbol.prototype?"symbol":typeof E},O(j)}var Qe=function(){var T=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},E=T.action,H=E===void 0?"copy":E,I=T.container,q=T.target,Me=T.text;if(H!=="copy"&&H!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&O(q)==="object"&&q.nodeType===1){if(H==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(H==="cut"&&(q.hasAttribute("readonly")||q.hasAttribute("disabled")))throw new Error(`Invalid "target" attribute. You can't cut text from elements with "readonly" or "disabled" attributes`)}else throw new Error('Invalid "target" value, use a valid Element');if(Me)return N(Me,{container:I});if(q)return H==="cut"?h(q):N(q,{container:I})},De=Qe;function $e(j){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?$e=function(E){return typeof E}:$e=function(E){return E&&typeof Symbol=="function"&&E.constructor===Symbol&&E!==Symbol.prototype?"symbol":typeof E},$e(j)}function Ei(j,T){if(!(j instanceof T))throw new TypeError("Cannot call a class as a function")}function tn(j,T){for(var E=0;E0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof I.action=="function"?I.action:this.defaultAction,this.target=typeof I.target=="function"?I.target:this.defaultTarget,this.text=typeof I.text=="function"?I.text:this.defaultText,this.container=$e(I.container)==="object"?I.container:document.body}},{key:"listenClick",value:function(I){var q=this;this.listener=c()(I,"click",function(Me){return q.onClick(Me)})}},{key:"onClick",value:function(I){var q=I.delegateTarget||I.currentTarget,Me=this.action(q)||"copy",kt=De({action:Me,container:this.container,target:this.target(q),text:this.text(q)});this.emit(kt?"success":"error",{action:Me,text:kt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(I){return vr("action",I)}},{key:"defaultTarget",value:function(I){var q=vr("target",I);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(I){return vr("text",I)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(I){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return N(I,q)}},{key:"cut",value:function(I){return h(I)}},{key:"isSupported",value:function(){var I=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof I=="string"?[I]:I,Me=!!document.queryCommandSupported;return q.forEach(function(kt){Me=Me&&!!document.queryCommandSupported(kt)}),Me}}]),E}(a()),Ai=Li},828:function(n){var o=9;if(typeof Element!="undefined"&&!Element.prototype.matches){var i=Element.prototype;i.matches=i.matchesSelector||i.mozMatchesSelector||i.msMatchesSelector||i.oMatchesSelector||i.webkitMatchesSelector}function s(a,f){for(;a&&a.nodeType!==o;){if(typeof a.matches=="function"&&a.matches(f))return a;a=a.parentNode}}n.exports=s},438:function(n,o,i){var s=i(828);function a(u,p,m,d,h){var v=c.apply(this,arguments);return u.addEventListener(m,v,h),{destroy:function(){u.removeEventListener(m,v,h)}}}function f(u,p,m,d,h){return typeof u.addEventListener=="function"?a.apply(null,arguments):typeof m=="function"?a.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return a(v,p,m,d,h)}))}function c(u,p,m,d){return function(h){h.delegateTarget=s(h.target,p),h.delegateTarget&&d.call(u,h)}}n.exports=f},879:function(n,o){o.node=function(i){return i!==void 0&&i instanceof HTMLElement&&i.nodeType===1},o.nodeList=function(i){var s=Object.prototype.toString.call(i);return i!==void 0&&(s==="[object NodeList]"||s==="[object HTMLCollection]")&&"length"in i&&(i.length===0||o.node(i[0]))},o.string=function(i){return typeof i=="string"||i instanceof String},o.fn=function(i){var s=Object.prototype.toString.call(i);return s==="[object Function]"}},370:function(n,o,i){var s=i(879),a=i(438);function f(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!s.string(d))throw new TypeError("Second argument must be a String");if(!s.fn(h))throw new TypeError("Third argument must be a Function");if(s.node(m))return c(m,d,h);if(s.nodeList(m))return u(m,d,h);if(s.string(m))return p(m,d,h);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList")}function c(m,d,h){return m.addEventListener(d,h),{destroy:function(){m.removeEventListener(d,h)}}}function u(m,d,h){return Array.prototype.forEach.call(m,function(v){v.addEventListener(d,h)}),{destroy:function(){Array.prototype.forEach.call(m,function(v){v.removeEventListener(d,h)})}}}function p(m,d,h){return a(document.body,m,d,h)}n.exports=f},817:function(n){function o(i){var s;if(i.nodeName==="SELECT")i.focus(),s=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var a=i.hasAttribute("readonly");a||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),a||i.removeAttribute("readonly"),s=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var f=window.getSelection(),c=document.createRange();c.selectNodeContents(i),f.removeAllRanges(),f.addRange(c),s=f.toString()}return s}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,s,a){var f=this.e||(this.e={});return(f[i]||(f[i]=[])).push({fn:s,ctx:a}),this},once:function(i,s,a){var f=this;function c(){f.off(i,c),s.apply(a,arguments)}return c._=s,this.on(i,c,a)},emit:function(i){var s=[].slice.call(arguments,1),a=((this.e||(this.e={}))[i]||[]).slice(),f=0,c=a.length;for(f;f{"use strict";/*! + * escape-html + * Copyright(c) 2012-2013 TJ Holowaychuk + * Copyright(c) 2015 Andreas Lubbe + * Copyright(c) 2015 Tiancheng "Timothy" Gu + * MIT Licensed + */var rs=/["'&<>]/;Yo.exports=ns;function ns(e){var t=""+e,r=rs.exec(t);if(!r)return t;var n,o="",i=0,s=0;for(i=r.index;i0&&i[i.length-1])&&(c[0]===6||c[0]===2)){r=0;continue}if(c[0]===3&&(!i||c[1]>i[0]&&c[1]=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function W(e,t){var r=typeof Symbol=="function"&&e[Symbol.iterator];if(!r)return e;var n=r.call(e),o,i=[],s;try{for(;(t===void 0||t-- >0)&&!(o=n.next()).done;)i.push(o.value)}catch(a){s={error:a}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(s)throw s.error}}return i}function D(e,t,r){if(r||arguments.length===2)for(var n=0,o=t.length,i;n1||a(m,d)})})}function a(m,d){try{f(n[m](d))}catch(h){p(i[0][3],h)}}function f(m){m.value instanceof et?Promise.resolve(m.value.v).then(c,u):p(i[0][2],m)}function c(m){a("next",m)}function u(m){a("throw",m)}function p(m,d){m(d),i.shift(),i.length&&a(i[0][0],i[0][1])}}function pn(e){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var t=e[Symbol.asyncIterator],r;return t?t.call(e):(e=typeof Ee=="function"?Ee(e):e[Symbol.iterator](),r={},n("next"),n("throw"),n("return"),r[Symbol.asyncIterator]=function(){return this},r);function n(i){r[i]=e[i]&&function(s){return new Promise(function(a,f){s=e[i](s),o(a,f,s.done,s.value)})}}function o(i,s,a,f){Promise.resolve(f).then(function(c){i({value:c,done:a})},s)}}function C(e){return typeof e=="function"}function at(e){var t=function(n){Error.call(n),n.stack=new Error().stack},r=e(t);return r.prototype=Object.create(Error.prototype),r.prototype.constructor=r,r}var It=at(function(e){return function(r){e(this),this.message=r?r.length+` errors occurred during unsubscription: +`+r.map(function(n,o){return o+1+") "+n.toString()}).join(` + `):"",this.name="UnsubscriptionError",this.errors=r}});function Ve(e,t){if(e){var r=e.indexOf(t);0<=r&&e.splice(r,1)}}var Ie=function(){function e(t){this.initialTeardown=t,this.closed=!1,this._parentage=null,this._finalizers=null}return e.prototype.unsubscribe=function(){var t,r,n,o,i;if(!this.closed){this.closed=!0;var s=this._parentage;if(s)if(this._parentage=null,Array.isArray(s))try{for(var a=Ee(s),f=a.next();!f.done;f=a.next()){var c=f.value;c.remove(this)}}catch(v){t={error:v}}finally{try{f&&!f.done&&(r=a.return)&&r.call(a)}finally{if(t)throw t.error}}else s.remove(this);var u=this.initialTeardown;if(C(u))try{u()}catch(v){i=v instanceof It?v.errors:[v]}var p=this._finalizers;if(p){this._finalizers=null;try{for(var m=Ee(p),d=m.next();!d.done;d=m.next()){var h=d.value;try{ln(h)}catch(v){i=i!=null?i:[],v instanceof It?i=D(D([],W(i)),W(v.errors)):i.push(v)}}}catch(v){n={error:v}}finally{try{d&&!d.done&&(o=m.return)&&o.call(m)}finally{if(n)throw n.error}}}if(i)throw new It(i)}},e.prototype.add=function(t){var r;if(t&&t!==this)if(this.closed)ln(t);else{if(t instanceof e){if(t.closed||t._hasParent(this))return;t._addParent(this)}(this._finalizers=(r=this._finalizers)!==null&&r!==void 0?r:[]).push(t)}},e.prototype._hasParent=function(t){var r=this._parentage;return r===t||Array.isArray(r)&&r.includes(t)},e.prototype._addParent=function(t){var r=this._parentage;this._parentage=Array.isArray(r)?(r.push(t),r):r?[r,t]:t},e.prototype._removeParent=function(t){var r=this._parentage;r===t?this._parentage=null:Array.isArray(r)&&Ve(r,t)},e.prototype.remove=function(t){var r=this._finalizers;r&&Ve(r,t),t instanceof e&&t._removeParent(this)},e.EMPTY=function(){var t=new e;return t.closed=!0,t}(),e}();var Sr=Ie.EMPTY;function jt(e){return e instanceof Ie||e&&"closed"in e&&C(e.remove)&&C(e.add)&&C(e.unsubscribe)}function ln(e){C(e)?e():e.unsubscribe()}var Le={onUnhandledError:null,onStoppedNotification:null,Promise:void 0,useDeprecatedSynchronousErrorHandling:!1,useDeprecatedNextContext:!1};var st={setTimeout:function(e,t){for(var r=[],n=2;n0},enumerable:!1,configurable:!0}),t.prototype._trySubscribe=function(r){return this._throwIfClosed(),e.prototype._trySubscribe.call(this,r)},t.prototype._subscribe=function(r){return this._throwIfClosed(),this._checkFinalizedStatuses(r),this._innerSubscribe(r)},t.prototype._innerSubscribe=function(r){var n=this,o=this,i=o.hasError,s=o.isStopped,a=o.observers;return i||s?Sr:(this.currentObservers=null,a.push(r),new Ie(function(){n.currentObservers=null,Ve(a,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,s=n.isStopped;o?r.error(i):s&&r.complete()},t.prototype.asObservable=function(){var r=new F;return r.source=this,r},t.create=function(r,n){return new xn(r,n)},t}(F);var xn=function(e){ie(t,e);function t(r,n){var o=e.call(this)||this;return o.destination=r,o.source=n,o}return t.prototype.next=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.next)===null||o===void 0||o.call(n,r)},t.prototype.error=function(r){var n,o;(o=(n=this.destination)===null||n===void 0?void 0:n.error)===null||o===void 0||o.call(n,r)},t.prototype.complete=function(){var r,n;(n=(r=this.destination)===null||r===void 0?void 0:r.complete)===null||n===void 0||n.call(r)},t.prototype._subscribe=function(r){var n,o;return(o=(n=this.source)===null||n===void 0?void 0:n.subscribe(r))!==null&&o!==void 0?o:Sr},t}(x);var Et={now:function(){return(Et.delegate||Date).now()},delegate:void 0};var wt=function(e){ie(t,e);function t(r,n,o){r===void 0&&(r=1/0),n===void 0&&(n=1/0),o===void 0&&(o=Et);var i=e.call(this)||this;return i._bufferSize=r,i._windowTime=n,i._timestampProvider=o,i._buffer=[],i._infiniteTimeWindow=!0,i._infiniteTimeWindow=n===1/0,i._bufferSize=Math.max(1,r),i._windowTime=Math.max(1,n),i}return t.prototype.next=function(r){var n=this,o=n.isStopped,i=n._buffer,s=n._infiniteTimeWindow,a=n._timestampProvider,f=n._windowTime;o||(i.push(r),!s&&i.push(a.now()+f)),this._trimBuffer(),e.prototype.next.call(this,r)},t.prototype._subscribe=function(r){this._throwIfClosed(),this._trimBuffer();for(var n=this._innerSubscribe(r),o=this,i=o._infiniteTimeWindow,s=o._buffer,a=s.slice(),f=0;f0?e.prototype.requestAsyncId.call(this,r,n,o):(r.actions.push(this),r._scheduled||(r._scheduled=ut.requestAnimationFrame(function(){return r.flush(void 0)})))},t.prototype.recycleAsyncId=function(r,n,o){var i;if(o===void 0&&(o=0),o!=null?o>0:this.delay>0)return e.prototype.recycleAsyncId.call(this,r,n,o);var s=r.actions;n!=null&&((i=s[s.length-1])===null||i===void 0?void 0:i.id)!==n&&(ut.cancelAnimationFrame(n),r._scheduled=void 0)},t}(Wt);var Sn=function(e){ie(t,e);function t(){return e!==null&&e.apply(this,arguments)||this}return t.prototype.flush=function(r){this._active=!0;var n=this._scheduled;this._scheduled=void 0;var o=this.actions,i;r=r||o.shift();do if(i=r.execute(r.state,r.delay))break;while((r=o[0])&&r.id===n&&o.shift());if(this._active=!1,i){for(;(r=o[0])&&r.id===n&&o.shift();)r.unsubscribe();throw i}},t}(Dt);var Oe=new Sn(wn);var _=new F(function(e){return e.complete()});function Vt(e){return e&&C(e.schedule)}function Cr(e){return e[e.length-1]}function Ye(e){return C(Cr(e))?e.pop():void 0}function Te(e){return Vt(Cr(e))?e.pop():void 0}function zt(e,t){return typeof Cr(e)=="number"?e.pop():t}var pt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function Nt(e){return C(e==null?void 0:e.then)}function qt(e){return C(e[ft])}function Kt(e){return Symbol.asyncIterator&&C(e==null?void 0:e[Symbol.asyncIterator])}function Qt(e){return new TypeError("You provided "+(e!==null&&typeof e=="object"?"an invalid object":"'"+e+"'")+" where a stream was expected. You can provide an Observable, Promise, ReadableStream, Array, AsyncIterable, or Iterable.")}function zi(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Yt=zi();function Gt(e){return C(e==null?void 0:e[Yt])}function Bt(e){return un(this,arguments,function(){var r,n,o,i;return $t(this,function(s){switch(s.label){case 0:r=e.getReader(),s.label=1;case 1:s.trys.push([1,,9,10]),s.label=2;case 2:return[4,et(r.read())];case 3:return n=s.sent(),o=n.value,i=n.done,i?[4,et(void 0)]:[3,5];case 4:return[2,s.sent()];case 5:return[4,et(o)];case 6:return[4,s.sent()];case 7:return s.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function Jt(e){return C(e==null?void 0:e.getReader)}function U(e){if(e instanceof F)return e;if(e!=null){if(qt(e))return Ni(e);if(pt(e))return qi(e);if(Nt(e))return Ki(e);if(Kt(e))return On(e);if(Gt(e))return Qi(e);if(Jt(e))return Yi(e)}throw Qt(e)}function Ni(e){return new F(function(t){var r=e[ft]();if(C(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function qi(e){return new F(function(t){for(var r=0;r=2;return function(n){return n.pipe(e?A(function(o,i){return e(o,i,n)}):de,ge(1),r?He(t):Dn(function(){return new Zt}))}}function Vn(){for(var e=[],t=0;t=2,!0))}function pe(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new x}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,s=i===void 0?!0:i,a=e.resetOnRefCountZero,f=a===void 0?!0:a;return function(c){var u,p,m,d=0,h=!1,v=!1,Y=function(){p==null||p.unsubscribe(),p=void 0},B=function(){Y(),u=m=void 0,h=v=!1},N=function(){var O=u;B(),O==null||O.unsubscribe()};return y(function(O,Qe){d++,!v&&!h&&Y();var De=m=m!=null?m:r();Qe.add(function(){d--,d===0&&!v&&!h&&(p=$r(N,f))}),De.subscribe(Qe),!u&&d>0&&(u=new rt({next:function($e){return De.next($e)},error:function($e){v=!0,Y(),p=$r(B,o,$e),De.error($e)},complete:function(){h=!0,Y(),p=$r(B,s),De.complete()}}),U(O).subscribe(u))})(c)}}function $r(e,t){for(var r=[],n=2;ne.next(document)),e}function K(e,t=document){return Array.from(t.querySelectorAll(e))}function z(e,t=document){let r=ce(e,t);if(typeof r=="undefined")throw new ReferenceError(`Missing element: expected "${e}" to be present`);return r}function ce(e,t=document){return t.querySelector(e)||void 0}function _e(){return document.activeElement instanceof HTMLElement&&document.activeElement||void 0}function tr(e){return L(b(document.body,"focusin"),b(document.body,"focusout")).pipe(ke(1),l(()=>{let t=_e();return typeof t!="undefined"?e.contains(t):!1}),V(e===_e()),J())}function Xe(e){return{x:e.offsetLeft,y:e.offsetTop}}function Kn(e){return L(b(window,"load"),b(window,"resize")).pipe(Ce(0,Oe),l(()=>Xe(e)),V(Xe(e)))}function rr(e){return{x:e.scrollLeft,y:e.scrollTop}}function dt(e){return L(b(e,"scroll"),b(window,"resize")).pipe(Ce(0,Oe),l(()=>rr(e)),V(rr(e)))}var Yn=function(){if(typeof Map!="undefined")return Map;function e(t,r){var n=-1;return t.some(function(o,i){return o[0]===r?(n=i,!0):!1}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(r){var n=e(this.__entries__,r),o=this.__entries__[n];return o&&o[1]},t.prototype.set=function(r,n){var o=e(this.__entries__,r);~o?this.__entries__[o][1]=n:this.__entries__.push([r,n])},t.prototype.delete=function(r){var n=this.__entries__,o=e(n,r);~o&&n.splice(o,1)},t.prototype.has=function(r){return!!~e(this.__entries__,r)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(r,n){n===void 0&&(n=null);for(var o=0,i=this.__entries__;o0},e.prototype.connect_=function(){!Wr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),va?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){!Wr||!this.connected_||(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(t){var r=t.propertyName,n=r===void 0?"":r,o=ba.some(function(i){return!!~n.indexOf(i)});o&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),Gn=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Jn=typeof WeakMap!="undefined"?new WeakMap:new Yn,Xn=function(){function e(t){if(!(this instanceof e))throw new TypeError("Cannot call a class as a function.");if(!arguments.length)throw new TypeError("1 argument required, but only 0 present.");var r=ga.getInstance(),n=new La(t,r,this);Jn.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){Xn.prototype[e]=function(){var t;return(t=Jn.get(this))[e].apply(t,arguments)}});var Aa=function(){return typeof nr.ResizeObserver!="undefined"?nr.ResizeObserver:Xn}(),Zn=Aa;var eo=new x,Ca=$(()=>k(new Zn(e=>{for(let t of e)eo.next(t)}))).pipe(g(e=>L(ze,k(e)).pipe(R(()=>e.disconnect()))),X(1));function he(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ye(e){return Ca.pipe(S(t=>t.observe(e)),g(t=>eo.pipe(A(({target:r})=>r===e),R(()=>t.unobserve(e)),l(()=>he(e)))),V(he(e)))}function bt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function ar(e){let t=e.parentElement;for(;t&&(e.scrollWidth<=t.scrollWidth&&e.scrollHeight<=t.scrollHeight);)t=(e=t).parentElement;return t?e:void 0}var to=new x,Ra=$(()=>k(new IntersectionObserver(e=>{for(let t of e)to.next(t)},{threshold:0}))).pipe(g(e=>L(ze,k(e)).pipe(R(()=>e.disconnect()))),X(1));function sr(e){return Ra.pipe(S(t=>t.observe(e)),g(t=>to.pipe(A(({target:r})=>r===e),R(()=>t.unobserve(e)),l(({isIntersecting:r})=>r))))}function ro(e,t=16){return dt(e).pipe(l(({y:r})=>{let n=he(e),o=bt(e);return r>=o.height-n.height-t}),J())}var cr={drawer:z("[data-md-toggle=drawer]"),search:z("[data-md-toggle=search]")};function no(e){return cr[e].checked}function Ke(e,t){cr[e].checked!==t&&cr[e].click()}function Ue(e){let t=cr[e];return b(t,"change").pipe(l(()=>t.checked),V(t.checked))}function ka(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function Ha(){return L(b(window,"compositionstart").pipe(l(()=>!0)),b(window,"compositionend").pipe(l(()=>!1))).pipe(V(!1))}function oo(){let e=b(window,"keydown").pipe(A(t=>!(t.metaKey||t.ctrlKey)),l(t=>({mode:no("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),A(({mode:t,type:r})=>{if(t==="global"){let n=_e();if(typeof n!="undefined")return!ka(n,r)}return!0}),pe());return Ha().pipe(g(t=>t?_:e))}function le(){return new URL(location.href)}function ot(e){location.href=e.href}function io(){return new x}function ao(e,t){if(typeof t=="string"||typeof t=="number")e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(let r of t)ao(e,r)}function M(e,t,...r){let n=document.createElement(e);if(t)for(let o of Object.keys(t))typeof t[o]!="undefined"&&(typeof t[o]!="boolean"?n.setAttribute(o,t[o]):n.setAttribute(o,""));for(let o of r)ao(n,o);return n}function fr(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function so(){return location.hash.substring(1)}function Dr(e){let t=M("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Pa(e){return L(b(window,"hashchange"),e).pipe(l(so),V(so()),A(t=>t.length>0),X(1))}function co(e){return Pa(e).pipe(l(t=>ce(`[id="${t}"]`)),A(t=>typeof t!="undefined"))}function Vr(e){let t=matchMedia(e);return er(r=>t.addListener(()=>r(t.matches))).pipe(V(t.matches))}function fo(){let e=matchMedia("print");return L(b(window,"beforeprint").pipe(l(()=>!0)),b(window,"afterprint").pipe(l(()=>!1))).pipe(V(e.matches))}function zr(e,t){return e.pipe(g(r=>r?t():_))}function ur(e,t={credentials:"same-origin"}){return ue(fetch(`${e}`,t)).pipe(fe(()=>_),g(r=>r.status!==200?Ot(()=>new Error(r.statusText)):k(r)))}function We(e,t){return ur(e,t).pipe(g(r=>r.json()),X(1))}function uo(e,t){let r=new DOMParser;return ur(e,t).pipe(g(n=>n.text()),l(n=>r.parseFromString(n,"text/xml")),X(1))}function pr(e){let t=M("script",{src:e});return $(()=>(document.head.appendChild(t),L(b(t,"load"),b(t,"error").pipe(g(()=>Ot(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(l(()=>{}),R(()=>document.head.removeChild(t)),ge(1))))}function po(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function lo(){return L(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(l(po),V(po()))}function mo(){return{width:innerWidth,height:innerHeight}}function ho(){return b(window,"resize",{passive:!0}).pipe(l(mo),V(mo()))}function bo(){return G([lo(),ho()]).pipe(l(([e,t])=>({offset:e,size:t})),X(1))}function lr(e,{viewport$:t,header$:r}){let n=t.pipe(ee("size")),o=G([n,r]).pipe(l(()=>Xe(e)));return G([r,t,o]).pipe(l(([{height:i},{offset:s,size:a},{x:f,y:c}])=>({offset:{x:s.x-f,y:s.y-c+i},size:a})))}(()=>{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(s=>{let a=document.createElement("script");a.src=i,a.onload=s,document.body.appendChild(a)})),Promise.resolve())}var r=class extends EventTarget{constructor(n){super(),this.url=n,this.m=i=>{i.source===this.w&&(this.dispatchEvent(new MessageEvent("message",{data:i.data})),this.onmessage&&this.onmessage(i))},this.e=(i,s,a,f,c)=>{if(s===`${this.url}`){let u=new ErrorEvent("error",{message:i,filename:s,lineno:a,colno:f,error:c});this.dispatchEvent(u),this.onerror&&this.onerror(u)}};let o=document.createElement("iframe");o.hidden=!0,document.body.appendChild(this.iframe=o),this.w.document.open(),this.w.document.write(` + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

cli

+

help

+

list

+

cmd

+

exe

+

cmd

+

exe python

+

cmd

+

exe pip

+

cmd

+

remove

+

cmd

+

manage

+

cmd

+

manage update

+

cmd

+

manage purge

+

cmd

+

manage show

+

cmd

+

manage install

+

cmd

+

freeze

+

cmd

+

shim

+

cmd

+

run

+

cmd

+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/index.html b/index.html index b4ab837..1042886 100644 --- a/index.html +++ b/index.html @@ -1,9 +1,598 @@ - - + + + - - - - + + + + + + + + + + + + + + + + + + viv + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +
+ + +
+ +
+ + + + + + +
+
+ + + +
+
+
+ + + + +
+
+
+ + + +
+
+
+ + + +
+
+
+ + + +
+
+ + + + + + + +

viv

+
+ + Logo + +

+ viv isn't venv +

+

+ Documentation +

+
+ +

Try before you buy!

+
python3 <(curl -fsSL viv.dayl.in/viv.py) run pycowsay -- "viv isn't venv\!"
+
+
+

Viv is a standalone dependency-free venv creator.

+

These venvs can be identified by name or by their specification. +In any case they will be re-used across scripts (and generated on-demand, if needed).

+

Importantly, viv will also remove your user site directory. +(view with: python -m 'import site;print(site.USER_SITE)').

+

Viv's uncompromising insistence on portability means that it will always (1) only use the standard library (2) never exceed a single script.

+

For that reason any usage of the CLI can be accomplished using a remote copy as seen in the below install command.

+

Setup

+

Run the below command to install viv.

+
python3 <(curl -fsSL viv.dayl.in/viv.py) manage install
+
+

To access viv from within scripts you should add it's location to your PYTHONPATH. +By default viv will be installed to $XDG_DATA_HOME/viv or ~/.local/share/viv you can customize this with --src.

+
export PYTHONPATH="$PYTHONPATH:$HOME/.local/share/viv"
+
+

Advanced users may recognize that principally, +the module just needs to be recognized at run time +and the single script viv.py can be invoked directly for the CLI. +How you accomplish these options is ultimately up to you but the above instructions can get you started.

+ +
pip install viv
+
+

Why is this not recommended? Mainly, because viv is all about hacking your sys.path. +Placing it in it's own virtual environment or installing in a user site directory may complicate this endeavor.

+

Usage

+

In any python script with external dependencies you can add this line, +to automate vivenv creation and installation of dependencies.

+
__import__("viv").use("click")
+
+

To remove all vivenvs you can use the below command:

+
viv remove $(viv list -q)
+
+

To remove viv all together you can use the included purge command:

+
python3 <(curl -fsSL viv.dayl.in/viv.py) manage purge
+
+

Additional Features

+

An experimental feature of viv is generating shim's that leverage the principles of viv. +These shims would operate similar to pipx in which you can specify a command line app to "install".

+

Note that --standalone will auto-generate a code-golfed minified version of viv to accomplish the same basic task as using a local copy of viv. +After generating this a standalone shim you can freely use this script across unix machines which have python>3.8. +See examples/black for output of below command.

+
python3 <(curl -fsSL viv.dayl.in/viv.py) shim black -o ./black --standalone --freeze
+
+

Alternatives

+

pip-run

+
pip-run (10.0.5)
+├── autocommand (2.2.2)
+├── jaraco-context (4.3.0)
+├── jaraco-functools (3.6.0)
+│   └── more-itertools (9.1.0)
+├── jaraco-text (3.11.1)
+│   ├── autocommand (2.2.2)
+│   ├── inflect (6.0.2)
+│   │   └── pydantic>=1.9.1 (1.10.5)
+│   │       └── typing-extensions>=4.2.0 (4.5.0)
+│   ├── jaraco-context>=4.1 (4.3.0)
+│   ├── jaraco-functools (3.6.0)
+│   │   └── more-itertools (9.1.0)
+│   └── more-itertools (9.1.0)
+├── more-itertools>=8.3 (9.1.0)
+├── packaging (23.0)
+├── path>=15.1 (16.6.0)
+├── pip>=19.3 (23.0.1)
+└── platformdirs (3.1.0)
+
+

pipx

+
pipx (1.1.0)
+├── argcomplete>=1.9.4 (2.1.1)
+├── packaging>=20.0 (23.0)
+└── userpath>=1.6.0 (1.8.0)
+    └── click (8.1.3)
+
+ + + + + + +
+
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 0000000..044254b --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"viv","text":"

viv isn't venv

Documentation

Try before you buy!

python3 <(curl -fsSL viv.dayl.in/viv.py) run pycowsay -- \"viv isn't venv\\!\"\n

Viv is a standalone dependency-free venv creator.

These venvs can be identified by name or by their specification. In any case they will be re-used across scripts (and generated on-demand, if needed).

Importantly, viv will also remove your user site directory. (view with: python -m 'import site;print(site.USER_SITE)').

Viv's uncompromising insistence on portability means that it will always (1) only use the standard library (2) never exceed a single script.

For that reason any usage of the CLI can be accomplished using a remote copy as seen in the below install command.

"},{"location":"#setup","title":"Setup","text":"

Run the below command to install viv.

python3 <(curl -fsSL viv.dayl.in/viv.py) manage install\n

To access viv from within scripts you should add it's location to your PYTHONPATH. By default viv will be installed to $XDG_DATA_HOME/viv or ~/.local/share/viv you can customize this with --src.

export PYTHONPATH=\"$PYTHONPATH:$HOME/.local/share/viv\"\n

Advanced users may recognize that principally, the module just needs to be recognized at run time and the single script viv.py can be invoked directly for the CLI. How you accomplish these options is ultimately up to you but the above instructions can get you started.

"},{"location":"#pypi-not-recommended","title":"Pypi (Not Recommended)","text":"
pip install viv\n

Why is this not recommended? Mainly, because viv is all about hacking your sys.path. Placing it in it's own virtual environment or installing in a user site directory may complicate this endeavor.

"},{"location":"#usage","title":"Usage","text":"

In any python script with external dependencies you can add this line, to automate vivenv creation and installation of dependencies.

__import__(\"viv\").use(\"click\")\n

To remove all vivenvs you can use the below command:

viv remove $(viv list -q)\n

To remove viv all together you can use the included purge command:

python3 <(curl -fsSL viv.dayl.in/viv.py) manage purge\n
"},{"location":"#additional-features","title":"Additional Features","text":"

An experimental feature of viv is generating shim's that leverage the principles of viv. These shims would operate similar to pipx in which you can specify a command line app to \"install\".

Note that --standalone will auto-generate a code-golfed minified version of viv to accomplish the same basic task as using a local copy of viv. After generating this a standalone shim you can freely use this script across unix machines which have python>3.8. See examples/black for output of below command.

python3 <(curl -fsSL viv.dayl.in/viv.py) shim black -o ./black --standalone --freeze\n
"},{"location":"#alternatives","title":"Alternatives","text":""},{"location":"#pip-run","title":"pip-run","text":"
pip-run (10.0.5)\n\u251c\u2500\u2500 autocommand (2.2.2)\n\u251c\u2500\u2500 jaraco-context (4.3.0)\n\u251c\u2500\u2500 jaraco-functools (3.6.0)\n\u2502   \u2514\u2500\u2500 more-itertools (9.1.0)\n\u251c\u2500\u2500 jaraco-text (3.11.1)\n\u2502   \u251c\u2500\u2500 autocommand (2.2.2)\n\u2502   \u251c\u2500\u2500 inflect (6.0.2)\n\u2502   \u2502   \u2514\u2500\u2500 pydantic>=1.9.1 (1.10.5)\n\u2502   \u2502       \u2514\u2500\u2500 typing-extensions>=4.2.0 (4.5.0)\n\u2502   \u251c\u2500\u2500 jaraco-context>=4.1 (4.3.0)\n\u2502   \u251c\u2500\u2500 jaraco-functools (3.6.0)\n\u2502   \u2502   \u2514\u2500\u2500 more-itertools (9.1.0)\n\u2502   \u2514\u2500\u2500 more-itertools (9.1.0)\n\u251c\u2500\u2500 more-itertools>=8.3 (9.1.0)\n\u251c\u2500\u2500 packaging (23.0)\n\u251c\u2500\u2500 path>=15.1 (16.6.0)\n\u251c\u2500\u2500 pip>=19.3 (23.0.1)\n\u2514\u2500\u2500 platformdirs (3.1.0)\n
"},{"location":"#pipx","title":"pipx","text":"
pipx (1.1.0)\n\u251c\u2500\u2500 argcomplete>=1.9.4 (2.1.1)\n\u251c\u2500\u2500 packaging>=20.0 (23.0)\n\u2514\u2500\u2500 userpath>=1.6.0 (1.8.0)\n    \u2514\u2500\u2500 click (8.1.3)\n
"},{"location":"cli/","title":"cli","text":""},{"location":"cli/#list","title":"list","text":""},{"location":"cli/#exe","title":"exe","text":""},{"location":"cli/#exe-python","title":"exe python","text":""},{"location":"cli/#exe-pip","title":"exe pip","text":""},{"location":"cli/#remove","title":"remove","text":""},{"location":"cli/#manage","title":"manage","text":""},{"location":"cli/#manage-update","title":"manage update","text":""},{"location":"cli/#manage-purge","title":"manage purge","text":""},{"location":"cli/#manage-show","title":"manage show","text":""},{"location":"cli/#manage-install","title":"manage install","text":""},{"location":"cli/#freeze","title":"freeze","text":""},{"location":"cli/#shim","title":"shim","text":""},{"location":"cli/#run","title":"run","text":""}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..0e9698d --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,13 @@ + + + + https://viv.dayl.in/ + 2023-06-01 + daily + + + https://viv.dayl.in/cli/ + 2023-06-01 + daily + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 0000000..41f7889 Binary files /dev/null and b/sitemap.xml.gz differ diff --git a/viv.py b/viv.py old mode 100755 new mode 100644 index 9cd27f5..d1369ab --- a/viv.py +++ b/viv.py @@ -9,6 +9,7 @@ from __future__ import annotations import hashlib +import inspect import itertools import json import os @@ -31,19 +32,17 @@ from argparse import ( _SubParsersAction, ) from argparse import ArgumentParser as StdArgParser +from dataclasses import dataclass from datetime import datetime -from itertools import zip_longest from pathlib import Path -from textwrap import dedent, fill, wrap +from textwrap import dedent, fill from types import TracebackType from typing import ( Any, Dict, - Generator, List, NoReturn, Optional, - Sequence, TextIO, Tuple, Type, @@ -51,7 +50,7 @@ from typing import ( from urllib.error import HTTPError from urllib.request import urlopen -__version__ = "23.5a4-13-ga6bd81d-dev" +__version__ = "23.5a4-15-gdf54955-dev" class Config: @@ -149,16 +148,6 @@ class Spinner: class Ansi: """control ouptut of ansi(VT100) control codes""" - BOX: Dict[str, str] = { - "v": "│", - "h": "─", - "tl": "╭", - "tr": "╮", - "bl": "╰", - "br": "╯", - "sep": "┆", - } - def __init__(self) -> None: self.bold: str = "\033[1m" self.dim: str = "\033[2m" @@ -229,104 +218,9 @@ class Ansi: new_output = [f"{self.red}->{self.end} {line}" for line in output.splitlines()] sys.stdout.write("\n".join(new_output) + "\n") - def _get_column_sizes( - self, rows: Tuple[Tuple[str, Sequence[str]], ...] - ) -> List[int]: - """convert list of rows to list of columns sizes - - First convert rows into list of columns, - then get max string length for each column. - """ - return list(max(map(len, lst)) for lst in map(list, zip(*rows))) # type: ignore - - def _make_row(self, row: Generator[Any, None, None]) -> str: - return ( - f" {self.BOX['v']} " - + f" {self.BOX['sep']} ".join(row) - + f" {self.BOX['v']}" - ) - - def _sanitize_row( - self, sizes: List[int], row: Tuple[str, Sequence[str]] - ) -> Tuple[Tuple[str, Sequence[str]], ...]: - if len(row[1]) > sizes[1]: - return tuple( - zip_longest( - (row[0],), - wrap(str(row[1]), break_on_hyphens=False, width=sizes[1]), - fillvalue="", - ) - ) - else: - return (row,) - def viv_preamble(self, style: str = "magenta", sep: str = "::") -> str: return f"{self.cyan}viv{self.end}{self.__dict__[style]}{sep}{self.end}" - def table( - self, rows: Tuple[Tuple[str, Sequence[str]], ...], header_style: str = "cyan" - ) -> None: - """generate a table with outline and styled header assumes two columns - - Args: - rows: sequence of the rows, first item assumed to be header - header_style: color/style for header row - """ - - sizes = self._get_column_sizes(rows) - - col2_limit = shutil.get_terminal_size().columns - 20 - if col2_limit < 20: - error("increase screen size to view table", code=1) - elif sizes[1] > col2_limit: - sizes[1] = col2_limit - - header, rows = rows[0], rows[1:] - # this is maybe taking comprehensions too far.... - table_rows = ( - self._make_row(row) - for row in ( - # header row - ( - self.__dict__[header_style] + f"{cell:<{sizes[i]}}" + self.end - for i, cell in enumerate(header) - ), - # rest of the rows - *( - (f"{cell:<{sizes[i]}}" for i, cell in enumerate(row)) - for row in ( - newrow - for row in rows - for newrow in self._sanitize_row(sizes, row) - ) - ), - ) - ) - - sys.stderr.write( - "".join( - ( - " ", - self.BOX["tl"], - self.BOX["h"] * (sum(sizes) + 5), - self.BOX["tr"], - "\n", - ) - ) - ) - sys.stderr.write("\n".join(table_rows) + "\n") - sys.stderr.write( - "".join( - ( - " ", - self.BOX["bl"], - self.BOX["h"] * (sum(sizes) + 5), - self.BOX["br"], - "\n", - ) - ) - ) - a = Ansi() @@ -339,26 +233,45 @@ to create/activate a vivenv: - from command line: `{a.style("viv -h","bold")}` - within python script: {a.style('__import__("viv").use("typer", "rich-click")','bold')} """ + _standalone_func = r"""def _viv_use(*pkgs, track_exe=False, name=""): - T,F,N=True,False,None;i,s,m,spec=__import__,str,map,[*pkgs] - e,w=lambda x: T if x else F,lambda p,t: p.write_text(t) - if not {*m(type,pkgs)}=={s}: raise ValueError(f"spec: {pkgs} is invalid") - ge,sys,P,ew=i("os").getenv,i("sys"),i("pathlib").Path,i("sys").stderr.write - (cache:=(P(ge("XDG_CACHE_HOME",P.home()/".cache"))/"viv"/"venvs")).mkdir(parents=T,exist_ok=T) - ((sha256:=i("hashlib").sha256()).update((s(spec)+ - (((exe:=("N/A",s(P(i("sys").executable).resolve()))[e(track_exe)])))).encode())) - if {env:=cache/(((_id:=sha256.hexdigest()),name)[e(name)])}-{*cache.glob("*/")} or ge("VIV_FORCE"): - v=e(ge("VIV_VERBOSE"));ew(f"generating new vivenv -> {env.name}\n") - i("venv").EnvBuilder(with_pip=T,clear=T).create(env) - w(env/"pip.conf","[global]\ndisable-pip-version-check=true") - if (rc:=(p:=i("subprocess").run([env/"bin"/"pip","install","--force-reinstall",*spec],text=T, - stdout=(-1,N)[v],stderr=(-2,N)[v])).returncode)!=0: - if env.is_dir():i("shutil").rmtree(env) - ew(f"pip had non zero exit ({rc})\n{p.stdout}\n");sys.exit(rc) - w(env/"viv-info.json",i("json").dumps( - {"created":s(i("datetime").datetime.today()),"id":_id,"spec":spec,"exe":exe})) - sys.path=[p for p in (*sys.path,s(*(env/"lib").glob("py*/si*")))if p!=i("site").USER_SITE] - return env""" # noqa + import hashlib, json, os, site, shutil, sys, venv # noqa + from pathlib import Path # noqa + from datetime import datetime # noqa + from subprocess import run # noqa + + if not {*map(type, pkgs)} == {str}: + raise ValueError(f"spec: {pkgs} is invalid") + + meta = dict.fromkeys(("created", "accessed"), (t := str(datetime.today()))) + runner = str(Path(__file__).absolute().resolve()) + force, verbose, xdg = map(os.getenv, ("VIV_FORCE", "VIV_VERBOSE", "XDG_CACHE_HOME")) + cache = (Path(xdg) if xdg else Path.home() / ".cache") / "viv" / "venvs" + cache.mkdir(parents=True, exist_ok=True) + exe = str(Path(sys.executable).resolve()) if track_exe else "N/A" + (sha256 := hashlib.sha256()).update((str(spec := [*pkgs]) + exe).encode()) + _id = sha256.hexdigest() + if (env := cache / (name if name else _id)) not in cache.glob("*/") or force: + sys.stderr.write(f"generating new vivenv -> {env.name}\n") + venv.EnvBuilder(with_pip=True, clear=True).create(env) + (env / "pip.conf").write_text("[global]\ndisable-pip-version-check=true") + run_kw = dict(zip(("stdout", "stderr"), ((None,) * 2 if verbose else (-1, 2)))) + p = run([env / "bin" / "pip", "install", "--force-reinstall", *spec], **run_kw) + if (rc := p.returncode) != 0: + if env.is_dir(): + shutil.rmtree(env) + sys.stderr.write(f"pip had non zero exit ({rc})\n{p.stdout.decode()}\n") + sys.exit(rc) + meta.update(dict(id=_id, spec=spec, exe=exe, name=name, files=[runner])) + else: + meta = json.loads((env / "vivmeta.json").read_text()) + meta.update(dict(accessed=t, files=sorted({*meta["files"],runner}))) + + (env / "vivmeta.json").write_text(json.dumps(meta)) + sys.path = [p for p in sys.path if not p != site.USER_SITE] + site.addsitedir(str(*(env / "lib").glob("py*/si*"))) + return env +""" def noqa(self, txt: str) -> str: max_length = max(map(len, txt.splitlines())) @@ -372,16 +285,13 @@ to create/activate a vivenv: return f"""__import__("viv").use({spec_str})""" def standalone(self, spec: List[str]) -> str: - func_use = self.noqa( - "\n".join((self._standalone_func, self._use_str(spec, standalone=True))) + func_use = "\n".join( + (self._standalone_func, self.noqa(self._use_str(spec, standalone=True))) ) return f""" -# see `python3 <(curl -fsSL gh.dayl.in/viv/viv.py) --help` -# <<<<< auto-generated by viv (v{__version__}) -# fmt: off +# see `python3 <(curl -fsSL viv.dayl.in/viv.py) --help` +# AUTOGENERATED by viv (v{__version__}) {func_use} -# fmt: on -# >>>>> code golfed with <3 """ def _rel_import(self, local_source: Optional[Path]) -> str: @@ -426,9 +336,7 @@ to create/activate a vivenv: bin: str, ) -> str: if standalone: - imports = "\n".join( - ("# fmt: off", self.noqa(self._standalone_func), "# fmt: on") - ) + imports = self._standalone_func elif path == "abs": imports = self._absolute_import(local_source) elif path == "rel": @@ -724,37 +632,78 @@ def get_hash(spec: Tuple[str, ...] | List[str], track_exe: bool = False) -> str: return sha256.hexdigest() +@dataclass +class Meta: + name: str + id: str + spec: List[str] + files: List[str] + exe: str + created: str = "" + accessed: str = "" + + @classmethod + def load(cls, name: str) -> "Meta": + if not (c.venvcache / name / "vivmeta.json").exists(): + warn(f"possibly corrupted vivenv: {name}") + # add empty values for corrupted vivenvs so it will still load + return cls(name=name, spec=[""], files=[""], exe="", id="") + else: + meta = json.loads((c.venvcache / name / "vivmeta.json").read_text()) + + return cls(**meta) + + def write(self, p: Path | None = None) -> None: + if not p: + p = (c.venvcache) / self.name / "vivmeta.json" + + p.write_text(json.dumps(self.__dict__)) + + def addfile(self, f: Path) -> None: + self.accessed = str(datetime.today()) + self.files = sorted({*self.files, str(f.absolute().resolve())}) + + class ViVenv: def __init__( self, - spec: List[str], + spec: List[str] = [""], track_exe: bool = False, id: str | None = None, name: str = "", path: Path | None = None, + skip_load: bool = False, + metadata: Meta | None = None, ) -> None: - self.spec = self._validate_spec(spec) - self.exe = str(Path(sys.executable).resolve()) if track_exe else "N/A" - self.id = id if id else get_hash(spec, track_exe) - self.name = name if name else self.id + self.loaded = False + spec = self._validate_spec(spec) + id = id if id else get_hash(spec, track_exe) + + self.name = name if name else id self.path = path if path else c.venvcache / self.name - self.exists = self.name in [d.name for d in c.venvcache.iterdir()] + + if not metadata: + if self.name in (d.name for d in c.venvcache.iterdir()): + self.loaded = True + self.meta = Meta.load(self.name) + else: + self.meta = Meta( + spec=spec, + name=self.name, + id=id, + files=[], + exe=str(Path(sys.executable).resolve()) if track_exe else "N/A", + ) + else: + self.meta = metadata @classmethod def load(cls, name: str) -> "ViVenv": - """generate a vivenv from a viv-info.json file + """generate a vivenv from a vivmeta.json Args: name: used as lookup in the vivenv cache """ - if not (c.venvcache / name / "viv-info.json").is_file(): - warn(f"possibly corrupted vivenv: {name}") - return cls(name=name, spec=[""]) - else: - with (c.venvcache / name / "viv-info.json").open("r") as f: - venvconfig = json.load(f) - - vivenv = cls(name=name, spec=venvconfig["spec"], id=venvconfig["id"]) - vivenv.exe = venvconfig["exe"] + vivenv = cls(name=name, metadata=Meta.load(name)) return vivenv @@ -781,12 +730,14 @@ class ViVenv: with (self.path / "pip.conf").open("w") as f: f.write("[global]\ndisable-pip-version-check = true") + self.meta.created = str(datetime.today()) + def install_pkgs(self) -> None: cmd: List[str] = [ str(self.path / "bin" / "pip"), "install", "--force-reinstall", - ] + self.spec + ] + self.meta.spec run( cmd, @@ -795,24 +746,57 @@ class ViVenv: verbose=bool(os.getenv("VIV_VERBOSE")), ) - def dump_info(self, write: bool = False) -> None: - # TODO: include associated files in 'info' - # means it needs to be loaded first - # or keep a seperate file hash in c.share? - info = { - "created": str(datetime.today()), - "id": self.id, - "spec": self.spec, - "exe": self.exe, - } + def show(self, verbose: bool = False) -> None: + if not verbose: + _id = ( + self.meta.id[:8] + if self.meta.id == self.name + else (self.name[:5] + "..." if len(self.name) > 8 else self.name) + ) - # save metadata to json file - if write: - with (self.path / "viv-info.json").open("w") as f: - json.dump(info, f) + sys.stdout.write( + f"""{a.bold}{a.cyan}{_id}{a.end} """ + f"""{a.style(", ".join(self.meta.spec),'dim')}\n""" + ) else: - info["spec"] = ", ".join(self.spec) - a.table((("key", "value"), *((k, v) for k, v in info.items()))) + self.tree() + + def _tree_leaves(self, items: List[str], indent: str = "") -> str: + tree_chars = ["├"] * (len(items) - 1) + ["╰"] + return "\n".join( + (f"{indent}{a.yellow}{c}─{a.end} {i}" for c, i in zip(tree_chars, items)) + ) + + def tree(self) -> None: + _id = self.meta.id if self.meta.id == self.name else self.name + # TODO: generarlize and loop this or make a template.. + items = [ + f"{a.magenta}{k}{a.end}: {v}" + for k, v in { + **{ + "spec": ", ".join(self.meta.spec), + "created": self.meta.created, + "accessed": self.meta.accessed, + }, + **({"exe": self.meta.exe} if self.meta.exe != "N/A" else {}), + **({"files": ""} if self.meta.files else {}), + }.items() + ] + rows = [f"\n{a.bold}{a.cyan}{_id}{a.end}", self._tree_leaves(items)] + if self.meta.files: + rows += (self._tree_leaves(self.meta.files, indent=" "),) + + sys.stdout.write("\n".join(rows) + "\n") + + +def get_caller_path() -> Path: + """get callers callers file path""" + # viv.py is fist in stack since function is used in `viv.use()` + frame_info = inspect.stack()[2] + filepath = frame_info.filename # in python 3.5+, you can use frame_info.filename + del frame_info # drop the reference to the stack frame to avoid reference cycles + + return Path(filepath).absolute() def use(*packages: str, track_exe: bool = False, name: str = "") -> Path: @@ -823,26 +807,22 @@ def use(*packages: str, track_exe: bool = False, name: str = "") -> Path: track_exe: if true make env python exe specific name: use as vivenv name, if not provided id is used """ - vivenv = ViVenv(list(packages), track_exe=track_exe, name=name) - if not vivenv.exists or os.getenv("VIV_FORCE"): + vivenv = ViVenv(list(packages), track_exe=track_exe, name=name) + if not vivenv.loaded or os.getenv("VIV_FORCE"): vivenv.create() vivenv.install_pkgs() - vivenv.dump_info(write=True) + + vivenv.meta.addfile(get_caller_path()) + vivenv.meta.write() modify_sys_path(vivenv.path) return vivenv.path def modify_sys_path(new_path: Path) -> None: - # remove user-site - for i, path in enumerate(sys.path): - if path == site.USER_SITE: - sys.path.pop(i) - - sys.path.append( - str([p for p in (new_path / "lib").glob("python*/site-packages")][0]) - ) + sys.path = [p for p in sys.path if p is not site.USER_SITE] + site.addsitedir(str(*(new_path / "lib").glob("python*/site-packages"))) def get_venvs() -> Dict[str, ViVenv]: @@ -923,9 +903,7 @@ class Viv: def __init__(self) -> None: self.vivenvs = get_venvs() self._get_sources() - self.name = ( - "viv" if self.local else "python3 <(curl -fsSL gh.dayl.in/viv/viv.py)" - ) + self.name = "viv" if self.local else "python3 <(curl -fsSL viv.dayl.in/viv.py)" def _get_sources(self) -> None: self.local_source: Optional[Path] = None @@ -954,7 +932,9 @@ class Viv: for k, v in self.vivenvs.items(): if name_id == k or v.name == name_id: matches.append(v) - elif k.startswith(name_id) or (v.id.startswith(name_id) and v.id == v.name): + elif k.startswith(name_id) or ( + v.meta.id.startswith(name_id) and v.meta.id == v.name + ): matches.append(v) elif v.name.startswith(name_id): matches.append(v) @@ -994,11 +974,10 @@ class Viv: # re-create env again since path's are hard-coded vivenv = ViVenv(spec) - if not vivenv.exists or os.getenv("VIV_FORCE"): + if not vivenv.loaded or os.getenv("VIV_FORCE"): vivenv.create() vivenv.install_pkgs() - vivenv.dump_info(write=True) - + vivenv.meta.write() else: echo("re-using existing vivenv") @@ -1021,19 +1000,8 @@ class Viv: elif len(self.vivenvs) == 0: echo("no vivenvs setup") else: - rows = ( - ("vivenv", "spec"), - *( - ( - f"{vivenv.name[:6]}..." - if len(vivenv.name) > 9 - else vivenv.name, - ", ".join(vivenv.spec), - ) - for vivenv in self.vivenvs.values() - ), - ) - a.table(rows) + for _, vivenv in self.vivenvs.items(): + vivenv.show(args.verbose) def exe(self, args: Namespace) -> None: """run python/pip in existing vivenv""" @@ -1056,14 +1024,12 @@ class Viv: def info(self, args: Namespace) -> None: """get metadata about a vivenv""" vivenv = self._match_vivenv(args.vivenv) - metadata_file = vivenv.path / "viv-info.json" + metadata_file = vivenv.path / "vivmeta.json" if not metadata_file.is_file(): error(f"Unable to find metadata for vivenv: {args.vivenv}", code=1) - echo(f"more info about {vivenv.name}:") - - vivenv.dump_info() + vivenv.show(verbose=True) def _install_local_src(self, sha256: str, src: Path, cli: Path) -> None: echo("updating local source copy of viv") @@ -1071,12 +1037,11 @@ class Viv: make_executable(src) echo("symlinking cli") - if cli.is_file() and confirm( - f"Existing file at {a.style(str(cli),'bold')}, " - "would you like to overwrite it?" - ): - cli.unlink() - cli.symlink_to(src) + if cli.is_file(): + echo(f"Existing file at {a.style(str(cli),'bold')}") + if confirm("Would you like to overwrite it?"): + cli.unlink() + cli.symlink_to(src) else: cli.symlink_to(src) @@ -1172,7 +1137,7 @@ class Viv: echo( "to re-install use: " - "`python3 <(curl -fsSL gh.dayl.in/viv/viv.py) manage install`" + "`python3 <(curl -fsSL viv.dayl.in/viv.py) manage install`" ) def _pick_bin(self, args: Namespace) -> Tuple[str, str]: @@ -1227,7 +1192,7 @@ class Viv: # ephemeral (default), semi-ephemeral (persist inside /tmp), or # persist (use c.cache) - if not vivenv.exists or os.getenv("VIV_FORCE"): + if not vivenv.loaded or os.getenv("VIV_FORCE"): if not args.keep: with tempfile.TemporaryDirectory(prefix="viv-") as tmpdir: vivenv.path = Path(tmpdir) @@ -1241,7 +1206,7 @@ class Viv: else: vivenv.create() vivenv.install_pkgs() - vivenv.dump_info(write=True) + vivenv.meta.write() sys.exit(subprocess.run([vivenv.path / "bin" / bin, *args.rest]).returncode) @@ -1265,7 +1230,7 @@ class Viv: return parser - def _validate_args(self, args): + def _validate_args(self, args: Namespace) -> None: if args.func.__name__ in ("freeze", "shim", "run"): if not args.reqs: error("must specify a requirement", code=1) @@ -1326,6 +1291,13 @@ class Viv: p_vivenv_arg.add_argument("vivenv", help="name/hash of vivenv") p_list = self._get_subcmd_parser(subparsers, "list") + p_list.add_argument( + "-v", + "--verbose", + help="show full metadata for vivenvs", + default=False, + action="store_true", + ) p_list.add_argument( "-q", "--quiet",