diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..78cd50f --- /dev/null +++ b/404.html @@ -0,0 +1 @@ + Phylm
\ No newline at end of file diff --git a/assets/_mkdocstrings.css b/assets/_mkdocstrings.css new file mode 100644 index 0000000..a65078d --- /dev/null +++ b/assets/_mkdocstrings.css @@ -0,0 +1,36 @@ + +/* Don't capitalize names. */ +h5.doc-heading { + text-transform: none !important; +} + +/* Avoid breaking parameters name, etc. in table cells. */ +.doc-contents td code { + word-break: normal !important; +} + +/* For pieces of Markdown rendered in table cells. */ +.doc-contents td p { + margin-top: 0 !important; + margin-bottom: 0 !important; +} + +/* Max width for docstring sections tables. */ +.doc .md-typeset__table, +.doc .md-typeset__table table { + display: table !important; + width: 100%; +} +.doc .md-typeset__table tr { + display: table-row; +} + +/* Avoid line breaks in rendered fields. */ +.field-body p { + display: inline; +} + +/* Defaults in Spacy table style. */ +.doc-param-default { + float: right; +} 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.6df46069.min.js b/assets/javascripts/bundle.6df46069.min.js new file mode 100644 index 0000000..02c8d5f --- /dev/null +++ b/assets/javascripts/bundle.6df46069.min.js @@ -0,0 +1,29 @@ +"use strict";(()=>{var Hi=Object.create;var xr=Object.defineProperty;var Pi=Object.getOwnPropertyDescriptor;var $i=Object.getOwnPropertyNames,Ht=Object.getOwnPropertySymbols,Ii=Object.getPrototypeOf,Er=Object.prototype.hasOwnProperty,an=Object.prototype.propertyIsEnumerable;var on=(e,t,r)=>t in e?xr(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r,P=(e,t)=>{for(var r in t||(t={}))Er.call(t,r)&&on(e,r,t[r]);if(Ht)for(var r of Ht(t))an.call(t,r)&&on(e,r,t[r]);return e};var sn=(e,t)=>{var r={};for(var n in e)Er.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&&an.call(e,n)&&(r[n]=e[n]);return r};var Pt=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Fi=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of $i(t))!Er.call(e,o)&&o!==r&&xr(e,o,{get:()=>t[o],enumerable:!(n=Pi(t,o))||n.enumerable});return e};var yt=(e,t,r)=>(r=e!=null?Hi(Ii(e)):{},Fi(t||!e||!e.__esModule?xr(r,"default",{value:e,enumerable:!0}):r,e));var fn=Pt((wr,cn)=>{(function(e,t){typeof wr=="object"&&typeof cn!="undefined"?t():typeof define=="function"&&define.amd?define(t):t()})(wr,function(){"use strict";function e(r){var n=!0,o=!1,i=null,a={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 s(T){return!!(T&&T!==document&&T.nodeName!=="HTML"&&T.nodeName!=="BODY"&&"classList"in T&&"contains"in T.classList)}function f(T){var Ke=T.type,De=T.tagName;return!!(De==="INPUT"&&a[Ke]&&!T.readOnly||De==="TEXTAREA"&&!T.readOnly||T.isContentEditable)}function c(T){T.classList.contains("focus-visible")||(T.classList.add("focus-visible"),T.setAttribute("data-focus-visible-added",""))}function u(T){T.hasAttribute("data-focus-visible-added")&&(T.classList.remove("focus-visible"),T.removeAttribute("data-focus-visible-added"))}function p(T){T.metaKey||T.altKey||T.ctrlKey||(s(r.activeElement)&&c(r.activeElement),n=!0)}function m(T){n=!1}function d(T){s(T.target)&&(n||f(T.target))&&c(T.target)}function h(T){s(T.target)&&(T.target.classList.contains("focus-visible")||T.target.hasAttribute("data-focus-visible-added"))&&(o=!0,window.clearTimeout(i),i=window.setTimeout(function(){o=!1},100),u(T.target))}function v(T){document.visibilityState==="hidden"&&(o&&(n=!0),B())}function B(){document.addEventListener("mousemove",z),document.addEventListener("mousedown",z),document.addEventListener("mouseup",z),document.addEventListener("pointermove",z),document.addEventListener("pointerdown",z),document.addEventListener("pointerup",z),document.addEventListener("touchmove",z),document.addEventListener("touchstart",z),document.addEventListener("touchend",z)}function ne(){document.removeEventListener("mousemove",z),document.removeEventListener("mousedown",z),document.removeEventListener("mouseup",z),document.removeEventListener("pointermove",z),document.removeEventListener("pointerdown",z),document.removeEventListener("pointerup",z),document.removeEventListener("touchmove",z),document.removeEventListener("touchstart",z),document.removeEventListener("touchend",z)}function z(T){T.target.nodeName&&T.target.nodeName.toLowerCase()==="html"||(n=!1,ne())}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),B(),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 un=Pt(Sr=>{(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," "))},a=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(ne,z){d.append(z,ne)})}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:Sr);(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(T){throw new Error("URL unable to set base "+c+" due to "+T)}}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,B=!0,ne=this;["append","delete","set"].forEach(function(T){var Ke=h[T];h[T]=function(){Ke.apply(h,arguments),v&&(B=!1,ne.search=h.toString(),B=!0)}}),Object.defineProperty(this,"searchParams",{value:h,enumerable:!0});var z=void 0;Object.defineProperty(this,"_updateSearchParams",{enumerable:!1,configurable:!1,writable:!1,value:function(){this.search!==z&&(z=this.search,B&&(v=!1,this.searchParams._fromString(this.search),v=!0))}})},a=i.prototype,s=function(f){Object.defineProperty(a,f,{get:function(){return this._anchorElement[f]},set:function(c){this._anchorElement[f]=c},enumerable:!0})};["hash","host","hostname","port","protocol"].forEach(function(f){s(f)}),Object.defineProperty(a,"search",{get:function(){return this._anchorElement.search},set:function(f){this._anchorElement.search=f,this._updateSearchParams()},enumerable:!0}),Object.defineProperties(a,{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:Sr)});var Qr=Pt((Lt,Kr)=>{/*! + * clipboard.js v2.0.11 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */(function(t,r){typeof Lt=="object"&&typeof Kr=="object"?Kr.exports=r():typeof define=="function"&&define.amd?define([],r):typeof Lt=="object"?Lt.ClipboardJS=r():t.ClipboardJS=r()})(Lt,function(){return function(){var e={686:function(n,o,i){"use strict";i.d(o,{default:function(){return ki}});var a=i(279),s=i.n(a),f=i(370),c=i.n(f),u=i(817),p=i.n(u);function m(j){try{return document.execCommand(j)}catch(O){return!1}}var d=function(O){var w=p()(O);return m("cut"),w},h=d;function v(j){var O=document.documentElement.getAttribute("dir")==="rtl",w=document.createElement("textarea");w.style.fontSize="12pt",w.style.border="0",w.style.padding="0",w.style.margin="0",w.style.position="absolute",w.style[O?"right":"left"]="-9999px";var k=window.pageYOffset||document.documentElement.scrollTop;return w.style.top="".concat(k,"px"),w.setAttribute("readonly",""),w.value=j,w}var B=function(O,w){var k=v(O);w.container.appendChild(k);var F=p()(k);return m("copy"),k.remove(),F},ne=function(O){var w=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body},k="";return typeof O=="string"?k=B(O,w):O instanceof HTMLInputElement&&!["text","search","url","tel","password"].includes(O==null?void 0:O.type)?k=B(O.value,w):(k=p()(O),m("copy")),k},z=ne;function T(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?T=function(w){return typeof w}:T=function(w){return w&&typeof Symbol=="function"&&w.constructor===Symbol&&w!==Symbol.prototype?"symbol":typeof w},T(j)}var Ke=function(){var O=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},w=O.action,k=w===void 0?"copy":w,F=O.container,q=O.target,Le=O.text;if(k!=="copy"&&k!=="cut")throw new Error('Invalid "action" value, use either "copy" or "cut"');if(q!==void 0)if(q&&T(q)==="object"&&q.nodeType===1){if(k==="copy"&&q.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if(k==="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(Le)return z(Le,{container:F});if(q)return k==="cut"?h(q):z(q,{container:F})},De=Ke;function Fe(j){return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?Fe=function(w){return typeof w}:Fe=function(w){return w&&typeof Symbol=="function"&&w.constructor===Symbol&&w!==Symbol.prototype?"symbol":typeof w},Fe(j)}function Ti(j,O){if(!(j instanceof O))throw new TypeError("Cannot call a class as a function")}function nn(j,O){for(var w=0;w0&&arguments[0]!==void 0?arguments[0]:{};this.action=typeof F.action=="function"?F.action:this.defaultAction,this.target=typeof F.target=="function"?F.target:this.defaultTarget,this.text=typeof F.text=="function"?F.text:this.defaultText,this.container=Fe(F.container)==="object"?F.container:document.body}},{key:"listenClick",value:function(F){var q=this;this.listener=c()(F,"click",function(Le){return q.onClick(Le)})}},{key:"onClick",value:function(F){var q=F.delegateTarget||F.currentTarget,Le=this.action(q)||"copy",kt=De({action:Le,container:this.container,target:this.target(q),text:this.text(q)});this.emit(kt?"success":"error",{action:Le,text:kt,trigger:q,clearSelection:function(){q&&q.focus(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(F){return yr("action",F)}},{key:"defaultTarget",value:function(F){var q=yr("target",F);if(q)return document.querySelector(q)}},{key:"defaultText",value:function(F){return yr("text",F)}},{key:"destroy",value:function(){this.listener.destroy()}}],[{key:"copy",value:function(F){var q=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{container:document.body};return z(F,q)}},{key:"cut",value:function(F){return h(F)}},{key:"isSupported",value:function(){var F=arguments.length>0&&arguments[0]!==void 0?arguments[0]:["copy","cut"],q=typeof F=="string"?[F]:F,Le=!!document.queryCommandSupported;return q.forEach(function(kt){Le=Le&&!!document.queryCommandSupported(kt)}),Le}}]),w}(s()),ki=Ri},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 a(s,f){for(;s&&s.nodeType!==o;){if(typeof s.matches=="function"&&s.matches(f))return s;s=s.parentNode}}n.exports=a},438:function(n,o,i){var a=i(828);function s(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"?s.apply(null,arguments):typeof m=="function"?s.bind(null,document).apply(null,arguments):(typeof u=="string"&&(u=document.querySelectorAll(u)),Array.prototype.map.call(u,function(v){return s(v,p,m,d,h)}))}function c(u,p,m,d){return function(h){h.delegateTarget=a(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 a=Object.prototype.toString.call(i);return i!==void 0&&(a==="[object NodeList]"||a==="[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 a=Object.prototype.toString.call(i);return a==="[object Function]"}},370:function(n,o,i){var a=i(879),s=i(438);function f(m,d,h){if(!m&&!d&&!h)throw new Error("Missing required arguments");if(!a.string(d))throw new TypeError("Second argument must be a String");if(!a.fn(h))throw new TypeError("Third argument must be a Function");if(a.node(m))return c(m,d,h);if(a.nodeList(m))return u(m,d,h);if(a.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 s(document.body,m,d,h)}n.exports=f},817:function(n){function o(i){var a;if(i.nodeName==="SELECT")i.focus(),a=i.value;else if(i.nodeName==="INPUT"||i.nodeName==="TEXTAREA"){var s=i.hasAttribute("readonly");s||i.setAttribute("readonly",""),i.select(),i.setSelectionRange(0,i.value.length),s||i.removeAttribute("readonly"),a=i.value}else{i.hasAttribute("contenteditable")&&i.focus();var f=window.getSelection(),c=document.createRange();c.selectNodeContents(i),f.removeAllRanges(),f.addRange(c),a=f.toString()}return a}n.exports=o},279:function(n){function o(){}o.prototype={on:function(i,a,s){var f=this.e||(this.e={});return(f[i]||(f[i]=[])).push({fn:a,ctx:s}),this},once:function(i,a,s){var f=this;function c(){f.off(i,c),a.apply(s,arguments)}return c._=a,this.on(i,c,s)},emit:function(i){var a=[].slice.call(arguments,1),s=((this.e||(this.e={}))[i]||[]).slice(),f=0,c=s.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 is=/["'&<>]/;Jo.exports=as;function as(e){var t=""+e,r=is.exec(t);if(!r)return t;var n,o="",i=0,a=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=[],a;try{for(;(t===void 0||t-- >0)&&!(o=n.next()).done;)i.push(o.value)}catch(s){a={error:s}}finally{try{o&&!o.done&&(r=n.return)&&r.call(n)}finally{if(a)throw a.error}}return i}function D(e,t,r){if(r||arguments.length===2)for(var n=0,o=t.length,i;n1||s(m,d)})})}function s(m,d){try{f(n[m](d))}catch(h){p(i[0][3],h)}}function f(m){m.value instanceof Ze?Promise.resolve(m.value.v).then(c,u):p(i[0][2],m)}function c(m){s("next",m)}function u(m){s("throw",m)}function p(m,d){m(d),i.shift(),i.length&&s(i[0][0],i[0][1])}}function mn(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 xe=="function"?xe(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(a){return new Promise(function(s,f){a=e[i](a),o(s,f,a.done,a.value)})}}function o(i,a,s,f){Promise.resolve(f).then(function(c){i({value:c,done:s})},a)}}function A(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 je=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 a=this._parentage;if(a)if(this._parentage=null,Array.isArray(a))try{for(var s=xe(a),f=s.next();!f.done;f=s.next()){var c=f.value;c.remove(this)}}catch(v){t={error:v}}finally{try{f&&!f.done&&(r=s.return)&&r.call(s)}finally{if(t)throw t.error}}else a.remove(this);var u=this.initialTeardown;if(A(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=xe(p),d=m.next();!d.done;d=m.next()){var h=d.value;try{dn(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)dn(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 Or=je.EMPTY;function Ft(e){return e instanceof je||e&&"closed"in e&&A(e.remove)&&A(e.add)&&A(e.unsubscribe)}function dn(e){A(e)?e():e.unsubscribe()}var Ae={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,a=o.isStopped,s=o.observers;return i||a?Or:(this.currentObservers=null,s.push(r),new je(function(){n.currentObservers=null,Ve(s,r)}))},t.prototype._checkFinalizedStatuses=function(r){var n=this,o=n.hasError,i=n.thrownError,a=n.isStopped;o?r.error(i):a&&r.complete()},t.prototype.asObservable=function(){var r=new U;return r.source=this,r},t.create=function(r,n){return new wn(r,n)},t}(U);var wn=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:Or},t}(E);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,a=n._infiniteTimeWindow,s=n._timestampProvider,f=n._windowTime;o||(i.push(r),!a&&i.push(s.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,a=o._buffer,s=a.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 a=r.actions;n!=null&&((i=a[a.length-1])===null||i===void 0?void 0:i.id)!==n&&(ut.cancelAnimationFrame(n),r._scheduled=void 0)},t}(Wt);var On=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 we=new On(Tn);var R=new U(function(e){return e.complete()});function Vt(e){return e&&A(e.schedule)}function kr(e){return e[e.length-1]}function Qe(e){return A(kr(e))?e.pop():void 0}function Se(e){return Vt(kr(e))?e.pop():void 0}function zt(e,t){return typeof kr(e)=="number"?e.pop():t}var pt=function(e){return e&&typeof e.length=="number"&&typeof e!="function"};function Nt(e){return A(e==null?void 0:e.then)}function qt(e){return A(e[ft])}function Kt(e){return Symbol.asyncIterator&&A(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 Ki(){return typeof Symbol!="function"||!Symbol.iterator?"@@iterator":Symbol.iterator}var Yt=Ki();function Gt(e){return A(e==null?void 0:e[Yt])}function Bt(e){return ln(this,arguments,function(){var r,n,o,i;return $t(this,function(a){switch(a.label){case 0:r=e.getReader(),a.label=1;case 1:a.trys.push([1,,9,10]),a.label=2;case 2:return[4,Ze(r.read())];case 3:return n=a.sent(),o=n.value,i=n.done,i?[4,Ze(void 0)]:[3,5];case 4:return[2,a.sent()];case 5:return[4,Ze(o)];case 6:return[4,a.sent()];case 7:return a.sent(),[3,2];case 8:return[3,10];case 9:return r.releaseLock(),[7];case 10:return[2]}})})}function Jt(e){return A(e==null?void 0:e.getReader)}function $(e){if(e instanceof U)return e;if(e!=null){if(qt(e))return Qi(e);if(pt(e))return Yi(e);if(Nt(e))return Gi(e);if(Kt(e))return _n(e);if(Gt(e))return Bi(e);if(Jt(e))return Ji(e)}throw Qt(e)}function Qi(e){return new U(function(t){var r=e[ft]();if(A(r.subscribe))return r.subscribe(t);throw new TypeError("Provided object does not correctly implement Symbol.observable")})}function Yi(e){return new U(function(t){for(var r=0;r=2;return function(n){return n.pipe(e?_(function(o,i){return e(o,i,n)}):de,Oe(1),r?Pe(t):zn(function(){return new Zt}))}}function Nn(){for(var e=[],t=0;t=2,!0))}function ue(e){e===void 0&&(e={});var t=e.connector,r=t===void 0?function(){return new E}:t,n=e.resetOnError,o=n===void 0?!0:n,i=e.resetOnComplete,a=i===void 0?!0:i,s=e.resetOnRefCountZero,f=s===void 0?!0:s;return function(c){var u,p,m,d=0,h=!1,v=!1,B=function(){p==null||p.unsubscribe(),p=void 0},ne=function(){B(),u=m=void 0,h=v=!1},z=function(){var T=u;ne(),T==null||T.unsubscribe()};return g(function(T,Ke){d++,!v&&!h&&B();var De=m=m!=null?m:r();Ke.add(function(){d--,d===0&&!v&&!h&&(p=jr(z,f))}),De.subscribe(Ke),!u&&d>0&&(u=new tt({next:function(Fe){return De.next(Fe)},error:function(Fe){v=!0,B(),p=jr(ne,o,Fe),De.error(Fe)},complete:function(){h=!0,B(),p=jr(ne,a),De.complete()}}),$(T).subscribe(u))})(c)}}function jr(e,t){for(var r=[],n=2;ne.next(document)),e}function K(e,t=document){return Array.from(t.querySelectorAll(e))}function V(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 rr(e){return L(b(document.body,"focusin"),b(document.body,"focusout")).pipe(He(1),l(()=>{let t=_e();return typeof t!="undefined"?e.contains(t):!1}),N(e===_e()),G())}function Je(e){return{x:e.offsetLeft,y:e.offsetTop}}function Yn(e){return L(b(window,"load"),b(window,"resize")).pipe(Re(0,we),l(()=>Je(e)),N(Je(e)))}function nr(e){return{x:e.scrollLeft,y:e.scrollTop}}function dt(e){return L(b(e,"scroll"),b(window,"resize")).pipe(Re(0,we),l(()=>nr(e)),N(nr(e)))}var Bn=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(){!zr||this.connected_||(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),xa?(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(){!zr||!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=ya.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}(),Jn=function(e,t){for(var r=0,n=Object.keys(t);r0},e}(),Zn=typeof WeakMap!="undefined"?new WeakMap:new Bn,eo=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=Ea.getInstance(),n=new Ra(t,r,this);Zn.set(this,n)}return e}();["observe","unobserve","disconnect"].forEach(function(e){eo.prototype[e]=function(){var t;return(t=Zn.get(this))[e].apply(t,arguments)}});var ka=function(){return typeof or.ResizeObserver!="undefined"?or.ResizeObserver:eo}(),to=ka;var ro=new E,Ha=I(()=>H(new to(e=>{for(let t of e)ro.next(t)}))).pipe(x(e=>L(Te,H(e)).pipe(C(()=>e.disconnect()))),J(1));function he(e){return{width:e.offsetWidth,height:e.offsetHeight}}function ge(e){return Ha.pipe(S(t=>t.observe(e)),x(t=>ro.pipe(_(({target:r})=>r===e),C(()=>t.unobserve(e)),l(()=>he(e)))),N(he(e)))}function bt(e){return{width:e.scrollWidth,height:e.scrollHeight}}function sr(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 no=new E,Pa=I(()=>H(new IntersectionObserver(e=>{for(let t of e)no.next(t)},{threshold:0}))).pipe(x(e=>L(Te,H(e)).pipe(C(()=>e.disconnect()))),J(1));function cr(e){return Pa.pipe(S(t=>t.observe(e)),x(t=>no.pipe(_(({target:r})=>r===e),C(()=>t.unobserve(e)),l(({isIntersecting:r})=>r))))}function oo(e,t=16){return dt(e).pipe(l(({y:r})=>{let n=he(e),o=bt(e);return r>=o.height-n.height-t}),G())}var fr={drawer:V("[data-md-toggle=drawer]"),search:V("[data-md-toggle=search]")};function io(e){return fr[e].checked}function qe(e,t){fr[e].checked!==t&&fr[e].click()}function Ue(e){let t=fr[e];return b(t,"change").pipe(l(()=>t.checked),N(t.checked))}function $a(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 Ia(){return L(b(window,"compositionstart").pipe(l(()=>!0)),b(window,"compositionend").pipe(l(()=>!1))).pipe(N(!1))}function ao(){let e=b(window,"keydown").pipe(_(t=>!(t.metaKey||t.ctrlKey)),l(t=>({mode:io("search")?"search":"global",type:t.key,claim(){t.preventDefault(),t.stopPropagation()}})),_(({mode:t,type:r})=>{if(t==="global"){let n=_e();if(typeof n!="undefined")return!$a(n,r)}return!0}),ue());return Ia().pipe(x(t=>t?R:e))}function Me(){return new URL(location.href)}function ot(e){location.href=e.href}function so(){return new E}function co(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)co(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)co(n,o);return n}function ur(e){if(e>999){let t=+((e-950)%1e3>99);return`${((e+1e-6)/1e3).toFixed(t)}k`}else return e.toString()}function fo(){return location.hash.substring(1)}function uo(e){let t=M("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function Fa(){return b(window,"hashchange").pipe(l(fo),N(fo()),_(e=>e.length>0),J(1))}function po(){return Fa().pipe(l(e=>ce(`[id="${e}"]`)),_(e=>typeof e!="undefined"))}function Nr(e){let t=matchMedia(e);return er(r=>t.addListener(()=>r(t.matches))).pipe(N(t.matches))}function lo(){let e=matchMedia("print");return L(b(window,"beforeprint").pipe(l(()=>!0)),b(window,"afterprint").pipe(l(()=>!1))).pipe(N(e.matches))}function qr(e,t){return e.pipe(x(r=>r?t():R))}function pr(e,t={credentials:"same-origin"}){return pe(fetch(`${e}`,t)).pipe(fe(()=>R),x(r=>r.status!==200?Tt(()=>new Error(r.statusText)):H(r)))}function We(e,t){return pr(e,t).pipe(x(r=>r.json()),J(1))}function mo(e,t){let r=new DOMParser;return pr(e,t).pipe(x(n=>n.text()),l(n=>r.parseFromString(n,"text/xml")),J(1))}function lr(e){let t=M("script",{src:e});return I(()=>(document.head.appendChild(t),L(b(t,"load"),b(t,"error").pipe(x(()=>Tt(()=>new ReferenceError(`Invalid script: ${e}`))))).pipe(l(()=>{}),C(()=>document.head.removeChild(t)),Oe(1))))}function ho(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function bo(){return L(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(l(ho),N(ho()))}function vo(){return{width:innerWidth,height:innerHeight}}function go(){return b(window,"resize",{passive:!0}).pipe(l(vo),N(vo()))}function yo(){return Q([bo(),go()]).pipe(l(([e,t])=>({offset:e,size:t})),J(1))}function mr(e,{viewport$:t,header$:r}){let n=t.pipe(X("size")),o=Q([n,r]).pipe(l(()=>Je(e)));return Q([r,t,o]).pipe(l(([{height:i},{offset:a,size:s},{x:f,y:c}])=>({offset:{x:a.x-f,y:a.y-c+i},size:s})))}(()=>{function e(n,o){parent.postMessage(n,o||"*")}function t(...n){return n.reduce((o,i)=>o.then(()=>new Promise(a=>{let s=document.createElement("script");s.src=i,s.onload=a,document.body.appendChild(s)})),Promise.resolve())}var r=class{constructor(n){this.url=n,this.onerror=null,this.onmessage=null,this.onmessageerror=null,this.m=a=>{a.source===this.w&&(a.stopImmediatePropagation(),this.dispatchEvent(new MessageEvent("message",{data:a.data})),this.onmessage&&this.onmessage(a))},this.e=(a,s,f,c,u)=>{if(s===this.url.toString()){let p=new ErrorEvent("error",{message:a,filename:s,lineno:f,colno:c,error:u});this.dispatchEvent(p),this.onerror&&this.onerror(p)}};let o=new EventTarget;this.addEventListener=o.addEventListener.bind(o),this.removeEventListener=o.removeEventListener.bind(o),this.dispatchEvent=o.dispatchEvent.bind(o);let i=document.createElement("iframe");i.width=i.height=i.frameBorder="0",document.body.appendChild(this.iframe=i),this.w.document.open(),this.w.document.write(`

Contributing

Issues

If you notice an issue with phylm or would like to suggest a feature or just have a general question, please raise an issue on GitHub. If it's an issue that needs debugging please make sure to include the version of phylm in the issue description. You can retrieve the version with the following:

pip freeze | grep phylm
+

Pull Requests

If you would like to contribute to the repo, you would be most welcome. If you're tackling an existing issue please comment on the issue that you'd like to take it on. If it's a new feature/bug, please first raise an issue. If it's a trivial change (typos, documentation etc.) then no need to raise an issue.

Local Development

In order to work on your contribution, you'll need to first fork the repo and then clone it to your local machine:

git clone git@github.com:<your username>/phylm.git
+cd phylm
+

You'll need python 3.8 or 3.9 to run this package. You can follow the instructions here to install and use these versions.

This package uses poetry to manage dependencies. Ensure you have poetry installed, instructions here and run:

poetry install
+

This will install the dependencies into a .venv virtual environment. You can activate the env with either source .venv/bin/activate or poetry shell.

Next install the pre-commit hooks with:

pre-commit install
+

Nox is used to run tests, linters, type checkers etc. These are all run in the CI and on git commit but if you'd like to run them manually, you can do so with, eg:

nox --session=tests
+

This will run the tests for all versions of python.

See here for more information on running nox locally.

If you're making changes that will require updates to the documentation, please do so accordingly. Documentation lives in the docs/ directory and can be served locally with:

mkdocs serve
+

See here for more information on working with mkdocs.

Once you're ready with your shiny, TDD'd feature, commit, push, and open a pull request and I'll be happy to review. If you're having issues with any of this setup please do let me know and I'll try and help.


Last update: 2023-10-18
\ No newline at end of file diff --git a/css/timeago.css b/css/timeago.css new file mode 100644 index 0000000..f7ab7d6 --- /dev/null +++ b/css/timeago.css @@ -0,0 +1,15 @@ +/* + timeago output is dynamic, which breaks when you print a page. + + This CSS is only included when type: timeago + and ensures fallback to type "iso_date" when printing. + + */ + +.git-revision-date-localized-plugin-iso_date { display: none } + +@media print { + .git-revision-date-localized-plugin-iso_date { display: inline } + .git-revision-date-localized-plugin-timeago { display: none } +} + diff --git a/imdb/index.html b/imdb/index.html new file mode 100644 index 0000000..3dce03f --- /dev/null +++ b/imdb/index.html @@ -0,0 +1,13 @@ + IMDb - Phylm

IMDb

Usage

To access IMDb data points, first ensure you have loaded the IMDb source through:

await phylm.load_source("imdb")
+

Alternatively you can instantiate the IMDb source class directly through:

from phylm.sources import Imdb
+
+imdb = Imdb(raw_title="The Matrix", raw_year=1999)  # raw_year is optional
+await imdb.load_source()
+

Movie ID

If you know the IMDb movie ID you can instantiate the Phylm class with an imdb_id property:

from phylm.sources import Imdb
+
+imdb = Imdb(raw_title="The Matrix", imdb_id="0133093")
+

Then, when running load_source for imdb, phylm will first perform a search based on the ID. If the ID is valid the result will be selected, if not then it will fall back to a title search.

Alternatively, you can pass it to load_source with "imdb" as the first argument:

await phylm.load_source("imdb", imdb_id="0133093")
+

Or instantiate the IMDb source class with the ID:

from phylm.sources import Imdb
+
+imdb = Imdb(movie_id="0133093")
+

If instantiating the class directly you must supply at least one of movie_id or raw_title, otherwise a ValueError will be raised.

Reference

Class to abstract an IMDb movie object.

id: Optional[str] property

Return the IMDb id.

Returns:

Type Description
Optional[str]

the id of the movie

plot: Optional[str] property

Return the plot.

Returns:

Type Description
Optional[str]

the plot of the movie

rating: Optional[float] property

Return the IMDb rating.

Returns:

Type Description
Optional[float]

the rating of the movie

runtime: Optional[str] property

Return the runtime.

Returns:

Type Description
Optional[str]

the runtime of the movie

title: Optional[str] property

Return the IMDb title.

Returns:

Type Description
Optional[str]

the title of the movie

year: Optional[int] property

Return the movie's year.

Returns:

Type Description
Optional[int]

the year the movie was made

__init__(raw_title: Optional[str] = None, movie_id: Optional[str] = None, raw_year: Optional[int] = None) -> None

Initialize the object.

Note that at least one of raw_title or movie_id must be given to be used as a search term. movie_id is preferred over raw_title.

Parameters:

Name Type Description Default
raw_title Optional[str]

the title of the movie

None
movie_id Optional[str]

the IMDb id of the movie

None
raw_year Optional[int]

an optional year for improved matching if only title is given

None

Raises:

Type Description
ValueError

if neither raw_title nor movie_id is supplied

cast(limit: int = 5) -> List[str]

Return the cast.

Parameters:

Name Type Description Default
limit int

an optional number of cast members to return

5

Returns:

Type Description
List[str]

a list of the movie's cast members

directors(limit: int = 3) -> List[str]

Return the director(s).

Parameters:

Name Type Description Default
limit int

an optional number of director to return

3

Returns:

Type Description
List[str]

a list of the movie's directors

genres(limit: int = 3) -> List[str]

Return the genres.

Parameters:

Name Type Description Default
limit int

an optional number of genres to return

3

Returns:

Type Description
List[str]

a list of the movie's genres

load_source() -> None async

Asynchronously load the data for from the source.


Last update: 2023-10-18
\ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..e04d6e7 --- /dev/null +++ b/index.html @@ -0,0 +1,8 @@ + Phylm

Phylm

Actions Status Actions Status codecov

When deciding which film to watch next, it can be helpful to have some key datapoints at your fingertips, for example, the genre, the cast, the Metacritic score and, perhaps most importantly, the runtime. This package provides a Phylm class to gather information from various sources for a given film.

Installing

pip install phylm
+

Example

>>> import asyncio
+>>> from phylm import Phylm
+>>> p = Phylm("The Matrix")
+>>> asyncio.run(p.load_source("imdb"))
+>>> p.imdb.rating
+8.7
+

This package uses web scraping for the Rotten Tomatoes and Metacritic results and is therefore at the mercy of changes made to those webpages.


Last update: 2023-10-18
\ No newline at end of file diff --git a/js/timeago.min.js b/js/timeago.min.js new file mode 100644 index 0000000..a8530a5 --- /dev/null +++ b/js/timeago.min.js @@ -0,0 +1,2 @@ +/* Taken from https://cdnjs.cloudflare.com/ajax/libs/timeago.js/4.0.2/timeago.min.js */ +!function(s,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((s=s||self).timeago={})}(this,function(s){"use strict";var a=["second","minute","hour","day","week","month","year"];function n(s,n){if(0===n)return["just now","right now"];var e=a[Math.floor(n/2)];return 1=m[t]&&t=m[e]&&e 0) { + var locale = nodes[0].getAttribute('locale'); + timeago.render(nodes, locale); + } + }) +} else { + var nodes = document.querySelectorAll('.timeago'); + if (nodes.length > 0) { + var locale = nodes[0].getAttribute('locale'); + timeago.render(nodes, locale); + } +} diff --git a/mtc/index.html b/mtc/index.html new file mode 100644 index 0000000..c8900ba --- /dev/null +++ b/mtc/index.html @@ -0,0 +1,6 @@ + Metacritic - Phylm

Metacritic

Usage

To access Metacritic data points, first ensure you have loaded the Metacritic source through:

await phylm.load_source("mtc")
+

Alternatively you can instantiate the Metacritic source class directly through:

from phylm.sources import Mtc
+
+mtc = Mtc(raw_title="The Matrix", raw_year=1999)  # raw_year is optional
+await mtc.load_source()
+

Reference

Class to abstract a Metacritic movie search result.

rating: Optional[str] property

Return the rating.

Returns:

Type Description
Optional[str]

the mtc rating

title: Optional[str] property

Return the title.

Returns:

Type Description
Optional[str]

the title of the movie

year: Optional[int] property

Return the year.

Returns:

Type Description
Optional[int]

the year of the movie

__init__(raw_title: str, raw_year: Optional[int] = None) -> None

Initialize the object.

Parameters:

Name Type Description Default
raw_title str

the given title of the movie

required
raw_year Optional[int]

an optional year for improved matching

None

load_source(session: Optional[ClientSession] = None) -> None async

Asynchronously load the data from the source.

Parameters:

Name Type Description Default
session Optional[ClientSession]

an optional instance of aiohttp.ClientSession in which to run the request

None

Last update: 2023-10-18
\ No newline at end of file diff --git a/objects.inv b/objects.inv new file mode 100644 index 0000000..0f3cd99 --- /dev/null +++ b/objects.inv @@ -0,0 +1,5 @@ +# Sphinx inventory version 2 +# Project: Phylm +# Version: 0.0.0 +# The remainder of this file is compressed using zlib. +xڕKK0𻟢W#^!&c7GLMvd:4cft˂QB`ڪxD.U4Pvi S49q)v8OwwwCP@HiIô\!3Ӄ֒d(Z/y:QtKU ^˚rbKlhi4I/PKԫ2B7}Q1H<(&EպRwSoDžOl `@Jb|T"~Tf}Vܒ&?Hg]>-%$oʭ@<q(*{ \ No newline at end of file diff --git a/phylm/index.html b/phylm/index.html new file mode 100644 index 0000000..2003a77 --- /dev/null +++ b/phylm/index.html @@ -0,0 +1,22 @@ + Phylm - Phylm

Phylm

This is the main entrypoint class.

Usage

First instantiate the class with a title property:

from phylm import Phylm
+
+p = Phylm(title="The Matrix")
+

You can also provide a year property for improved matching:

from phylm import Phylm
+
+p = Phylm(title="The Matrix", year=1999)
+

Next, asynchronously load a source through either load_sources or load_source:

await p.load_sources(["imdb", "rt"])
+await p.load_source("mtc")
+

The available sources are:

"imdb" # IMDb
+"rt" # Rotten Tomatoes
+"mtc" # Metacritic
+"tmdb" # TMDB
+

Now the source will be available through a property of the same name and datapoints on that source can be accessed:

>>> p.imdb
+<phylm.sources.imdb.Imdb object at 0x108a94810>
+>>> p.imdb.rating
+8.8
+

Low Confidence

phylm will try to match the given title with the results through an exact match on the title. If phylm can't find an exact match then it will select the first result and set a low_confidence flag to True. This and the year method on a source can be helpful for validating that the result is the desired one:

from phylm import Phylm
+p = Phylm("Ambiguous Movie")  # suppose this movie was released in 1999
+await p.load_source("imdb")
+if p.imdb.low_confidence and p.imdb.year != 1999:
+    # it's unlikely we're dealing with the right "Ambigous Movie"
+

See the docs for a source for a full list of the available data points.

Reference

Main Phylm entrypoint.

imdb: Imdb property

Return the IMDb data.

Returns:

Type Description
Imdb

The IMDb data

Raises:

Type Description
SourceNotLoadedError

if the source is not loaded

mtc: Mtc property

Return the Metacritic data.

Returns:

Type Description
Mtc

The Metacritic data

Raises:

Type Description
SourceNotLoadedError

if the source is not loaded

rt: Rt property

Return the Rotten Tomatoes data.

Returns:

Type Description
Rt

The Rotten Tomatoes data

Raises:

Type Description
SourceNotLoadedError

if the source is not loaded

tmdb: Tmdb property

Return the TMDB data.

Returns:

Type Description
Tmdb

The TMDB data

Raises:

Type Description
SourceNotLoadedError

if the source is not loaded

__init__(title: str, imdb_id: Optional[str] = None, year: Optional[int] = None, tmdb_id: Optional[str] = None) -> None

Initialize a Phylm object.

Parameters:

Name Type Description Default
title str

the title of the movie

required
imdb_id Optional[str]

an optional IMDb ID of the movie

None
year Optional[int]

an optional year of the movie

None
tmdb_id Optional[str]

an optional TMDB ID of the movie

None

load_source(source: str, imdb_id: Optional[str] = None, session: Optional[ClientSession] = None, tmdb_id: Optional[str] = None) -> Phylm async

Asynchronously load the film data for a source.

Parameters:

Name Type Description Default
source str

the desired source

required
imdb_id Optional[str]

an optional IMDb id which will be used to load the imdb data instead of a basic search on the title

None
session Optional[ClientSession]

an optional instance of aiohttp.ClientSession in which to run the request

None
tmdb_id Optional[str]

an optional TMDB id which will be used to load the TMDB data instead of a basic search on the title

None

Returns:

Type Description
Phylm

the instance

Raises:

Type Description
UnrecognizedSourceError

if the source is not recognized

load_sources(sources: List[str]) -> Phylm async

Asynchronously load multiple sources.

Parameters:

Name Type Description Default
sources List[str]

a list of the desired sources

required

Returns:

Type Description
Phylm

the instance


Last update: 2023-10-18
\ No newline at end of file diff --git a/rt/index.html b/rt/index.html new file mode 100644 index 0000000..2532e53 --- /dev/null +++ b/rt/index.html @@ -0,0 +1,6 @@ + Rotten Tomatoes - Phylm

Rotten Tomatoes

Usage

To access Rotten Tomatoes data points, first ensure you have loaded the Rotten Tomatoes source through:

await phylm.load_source("rt")
+

Alternatively you can instantiate the Rotten Tomatoes source class directly through:

from phylm.sources import Rt
+
+rot_tom = Rt(raw_title="The Matrix", raw_year=1999)  # raw_year is optional
+await rot_tom.load_source()
+

Reference

Class to abstract a Rotten Tomatoes result.

title: Optional[str] property

Return the title.

Returns:

Type Description
Optional[str]

the title of the movie

tomato_score: Optional[str] property

Return the Tomatometer Score.

Returns:

Type Description
Optional[str]

the tomatometer score

year: Optional[str] property

Return the year.

Returns:

Type Description
Optional[str]

the year of the movie

__init__(raw_title: str, raw_year: Optional[int] = None) -> None

Initialize the object.

Parameters:

Name Type Description Default
raw_title str

the given title of the movie

required
raw_year Optional[int]

an optional year for improved matching

None

load_source(session: Optional[ClientSession] = None) -> None async

Asynchronously load the data from the source.

Parameters:

Name Type Description Default
session Optional[ClientSession]

an optional instance of aiohttp.ClientSession in which to run the request

None

Last update: 2023-10-18
\ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 0000000..f13db26 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Phylm","text":"

When deciding which film to watch next, it can be helpful to have some key datapoints at your fingertips, for example, the genre, the cast, the Metacritic score and, perhaps most importantly, the runtime. This package provides a Phylm class to gather information from various sources for a given film.

"},{"location":"#installing","title":"Installing","text":"
pip install phylm\n
"},{"location":"#example","title":"Example","text":"
>>> import asyncio\n>>> from phylm import Phylm\n>>> p = Phylm(\"The Matrix\")\n>>> asyncio.run(p.load_source(\"imdb\"))\n>>> p.imdb.rating\n8.7\n

This package uses web scraping for the Rotten Tomatoes and Metacritic results and is therefore at the mercy of changes made to those webpages.

"},{"location":"contributing/","title":"Contributing","text":""},{"location":"contributing/#issues","title":"Issues","text":"

If you notice an issue with phylm or would like to suggest a feature or just have a general question, please raise an issue on GitHub. If it's an issue that needs debugging please make sure to include the version of phylm in the issue description. You can retrieve the version with the following:

pip freeze | grep phylm\n
"},{"location":"contributing/#pull-requests","title":"Pull Requests","text":"

If you would like to contribute to the repo, you would be most welcome. If you're tackling an existing issue please comment on the issue that you'd like to take it on. If it's a new feature/bug, please first raise an issue. If it's a trivial change (typos, documentation etc.) then no need to raise an issue.

"},{"location":"contributing/#local-development","title":"Local Development","text":"

In order to work on your contribution, you'll need to first fork the repo and then clone it to your local machine:

git clone git@github.com:<your username>/phylm.git\ncd phylm\n

You'll need python 3.8 or 3.9 to run this package. You can follow the instructions here to install and use these versions.

This package uses poetry to manage dependencies. Ensure you have poetry installed, instructions here and run:

poetry install\n

This will install the dependencies into a .venv virtual environment. You can activate the env with either source .venv/bin/activate or poetry shell.

Next install the pre-commit hooks with:

pre-commit install\n

Nox is used to run tests, linters, type checkers etc. These are all run in the CI and on git commit but if you'd like to run them manually, you can do so with, eg:

nox --session=tests\n

This will run the tests for all versions of python.

See here for more information on running nox locally.

If you're making changes that will require updates to the documentation, please do so accordingly. Documentation lives in the docs/ directory and can be served locally with:

mkdocs serve\n

See here for more information on working with mkdocs.

Once you're ready with your shiny, TDD'd feature, commit, push, and open a pull request and I'll be happy to review. If you're having issues with any of this setup please do let me know and I'll try and help.

"},{"location":"imdb/","title":"IMDb","text":""},{"location":"imdb/#usage","title":"Usage","text":"

To access IMDb data points, first ensure you have loaded the IMDb source through:

await phylm.load_source(\"imdb\")\n

Alternatively you can instantiate the IMDb source class directly through:

from phylm.sources import Imdb\n\nimdb = Imdb(raw_title=\"The Matrix\", raw_year=1999) \u00a0# raw_year is optional\nawait imdb.load_source()\n
"},{"location":"imdb/#movie-id","title":"Movie ID","text":"

If you know the IMDb movie ID you can instantiate the Phylm class with an imdb_id property:

from phylm.sources import Imdb\n\nimdb = Imdb(raw_title=\"The Matrix\", imdb_id=\"0133093\")\n

Then, when running load_source for imdb, phylm will first perform a search based on the ID. If the ID is valid the result will be selected, if not then it will fall back to a title search.

Alternatively, you can pass it to load_source with \"imdb\" as the first argument:

await phylm.load_source(\"imdb\", imdb_id=\"0133093\")\n

Or instantiate the IMDb source class with the ID:

from phylm.sources import Imdb\n\nimdb = Imdb(movie_id=\"0133093\")\n

If instantiating the class directly you must supply at least one of movie_id or raw_title, otherwise a ValueError will be raised.

"},{"location":"imdb/#reference","title":"Reference","text":"

Class to abstract an IMDb movie object.

"},{"location":"imdb/#phylm.sources.imdb.Imdb.id","title":"id: Optional[str] property","text":"

Return the IMDb id.

Returns:

Type Description Optional[str]

the id of the movie

"},{"location":"imdb/#phylm.sources.imdb.Imdb.plot","title":"plot: Optional[str] property","text":"

Return the plot.

Returns:

Type Description Optional[str]

the plot of the movie

"},{"location":"imdb/#phylm.sources.imdb.Imdb.rating","title":"rating: Optional[float] property","text":"

Return the IMDb rating.

Returns:

Type Description Optional[float]

the rating of the movie

"},{"location":"imdb/#phylm.sources.imdb.Imdb.runtime","title":"runtime: Optional[str] property","text":"

Return the runtime.

Returns:

Type Description Optional[str]

the runtime of the movie

"},{"location":"imdb/#phylm.sources.imdb.Imdb.title","title":"title: Optional[str] property","text":"

Return the IMDb title.

Returns:

Type Description Optional[str]

the title of the movie

"},{"location":"imdb/#phylm.sources.imdb.Imdb.year","title":"year: Optional[int] property","text":"

Return the movie's year.

Returns:

Type Description Optional[int]

the year the movie was made

"},{"location":"imdb/#phylm.sources.imdb.Imdb.__init__","title":"__init__(raw_title: Optional[str] = None, movie_id: Optional[str] = None, raw_year: Optional[int] = None) -> None","text":"

Initialize the object.

Note that at least one of raw_title or movie_id must be given to be used as a search term. movie_id is preferred over raw_title.

Parameters:

Name Type Description Default raw_title Optional[str]

the title of the movie

None movie_id Optional[str]

the IMDb id of the movie

None raw_year Optional[int]

an optional year for improved matching if only title is given

None

Raises:

Type Description ValueError

if neither raw_title nor movie_id is supplied

"},{"location":"imdb/#phylm.sources.imdb.Imdb.cast","title":"cast(limit: int = 5) -> List[str]","text":"

Return the cast.

Parameters:

Name Type Description Default limit int

an optional number of cast members to return

5

Returns:

Type Description List[str]

a list of the movie's cast members

"},{"location":"imdb/#phylm.sources.imdb.Imdb.directors","title":"directors(limit: int = 3) -> List[str]","text":"

Return the director(s).

Parameters:

Name Type Description Default limit int

an optional number of director to return

3

Returns:

Type Description List[str]

a list of the movie's directors

"},{"location":"imdb/#phylm.sources.imdb.Imdb.genres","title":"genres(limit: int = 3) -> List[str]","text":"

Return the genres.

Parameters:

Name Type Description Default limit int

an optional number of genres to return

3

Returns:

Type Description List[str]

a list of the movie's genres

"},{"location":"imdb/#phylm.sources.imdb.Imdb.load_source","title":"load_source() -> None async","text":"

Asynchronously load the data for from the source.

"},{"location":"mtc/","title":"Metacritic","text":""},{"location":"mtc/#usage","title":"Usage","text":"

To access Metacritic data points, first ensure you have loaded the Metacritic source through:

await phylm.load_source(\"mtc\")\n

Alternatively you can instantiate the Metacritic source class directly through:

from phylm.sources import Mtc\n\nmtc = Mtc(raw_title=\"The Matrix\", raw_year=1999) \u00a0# raw_year is optional\nawait mtc.load_source()\n
"},{"location":"mtc/#reference","title":"Reference","text":"

Class to abstract a Metacritic movie search result.

"},{"location":"mtc/#phylm.sources.mtc.Mtc.rating","title":"rating: Optional[str] property","text":"

Return the rating.

Returns:

Type Description Optional[str]

the mtc rating

"},{"location":"mtc/#phylm.sources.mtc.Mtc.title","title":"title: Optional[str] property","text":"

Return the title.

Returns:

Type Description Optional[str]

the title of the movie

"},{"location":"mtc/#phylm.sources.mtc.Mtc.year","title":"year: Optional[int] property","text":"

Return the year.

Returns:

Type Description Optional[int]

the year of the movie

"},{"location":"mtc/#phylm.sources.mtc.Mtc.__init__","title":"__init__(raw_title: str, raw_year: Optional[int] = None) -> None","text":"

Initialize the object.

Parameters:

Name Type Description Default raw_title str

the given title of the movie

required raw_year Optional[int]

an optional year for improved matching

None"},{"location":"mtc/#phylm.sources.mtc.Mtc.load_source","title":"load_source(session: Optional[ClientSession] = None) -> None async","text":"

Asynchronously load the data from the source.

Parameters:

Name Type Description Default session Optional[ClientSession]

an optional instance of aiohttp.ClientSession in which to run the request

None"},{"location":"phylm/","title":"Phylm","text":"

This is the main entrypoint class.

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

First instantiate the class with a title property:

from phylm import Phylm\n\np = Phylm(title=\"The Matrix\")\n

You can also provide a year property for improved matching:

from phylm import Phylm\n\np = Phylm(title=\"The Matrix\", year=1999)\n

Next, asynchronously load a source through either load_sources or load_source:

await p.load_sources([\"imdb\", \"rt\"])\nawait p.load_source(\"mtc\")\n

The available sources are:

\"imdb\" # IMDb\n\"rt\" # Rotten Tomatoes\n\"mtc\" # Metacritic\n\"tmdb\" # TMDB\n

Now the source will be available through a property of the same name and datapoints on that source can be accessed:

>>> p.imdb\n<phylm.sources.imdb.Imdb object at 0x108a94810>\n>>> p.imdb.rating\n8.8\n
"},{"location":"phylm/#low-confidence","title":"Low Confidence","text":"

phylm will try to match the given title with the results through an exact match on the title. If phylm can't find an exact match then it will select the first result and set a low_confidence flag to True. This and the year method on a source can be helpful for validating that the result is the desired one:

from phylm import Phylm\np = Phylm(\"Ambiguous Movie\")  # suppose this movie was released in 1999\nawait p.load_source(\"imdb\")\nif p.imdb.low_confidence and p.imdb.year != 1999:\n    # it's unlikely we're dealing with the right \"Ambigous Movie\"\n

See the docs for a source for a full list of the available data points.

"},{"location":"phylm/#reference","title":"Reference","text":"

Main Phylm entrypoint.

"},{"location":"phylm/#phylm.phylm.Phylm.imdb","title":"imdb: Imdb property","text":"

Return the IMDb data.

Returns:

Type Description Imdb

The IMDb data

Raises:

Type Description SourceNotLoadedError

if the source is not loaded

"},{"location":"phylm/#phylm.phylm.Phylm.mtc","title":"mtc: Mtc property","text":"

Return the Metacritic data.

Returns:

Type Description Mtc

The Metacritic data

Raises:

Type Description SourceNotLoadedError

if the source is not loaded

"},{"location":"phylm/#phylm.phylm.Phylm.rt","title":"rt: Rt property","text":"

Return the Rotten Tomatoes data.

Returns:

Type Description Rt

The Rotten Tomatoes data

Raises:

Type Description SourceNotLoadedError

if the source is not loaded

"},{"location":"phylm/#phylm.phylm.Phylm.tmdb","title":"tmdb: Tmdb property","text":"

Return the TMDB data.

Returns:

Type Description Tmdb

The TMDB data

Raises:

Type Description SourceNotLoadedError

if the source is not loaded

"},{"location":"phylm/#phylm.phylm.Phylm.__init__","title":"__init__(title: str, imdb_id: Optional[str] = None, year: Optional[int] = None, tmdb_id: Optional[str] = None) -> None","text":"

Initialize a Phylm object.

Parameters:

Name Type Description Default title str

the title of the movie

required imdb_id Optional[str]

an optional IMDb ID of the movie

None year Optional[int]

an optional year of the movie

None tmdb_id Optional[str]

an optional TMDB ID of the movie

None"},{"location":"phylm/#phylm.phylm.Phylm.load_source","title":"load_source(source: str, imdb_id: Optional[str] = None, session: Optional[ClientSession] = None, tmdb_id: Optional[str] = None) -> Phylm async","text":"

Asynchronously load the film data for a source.

Parameters:

Name Type Description Default source str

the desired source

required imdb_id Optional[str]

an optional IMDb id which will be used to load the imdb data instead of a basic search on the title

None session Optional[ClientSession]

an optional instance of aiohttp.ClientSession in which to run the request

None tmdb_id Optional[str]

an optional TMDB id which will be used to load the TMDB data instead of a basic search on the title

None

Returns:

Type Description Phylm

the instance

Raises:

Type Description UnrecognizedSourceError

if the source is not recognized

"},{"location":"phylm/#phylm.phylm.Phylm.load_sources","title":"load_sources(sources: List[str]) -> Phylm async","text":"

Asynchronously load multiple sources.

Parameters:

Name Type Description Default sources List[str]

a list of the desired sources

required

Returns:

Type Description Phylm

the instance

"},{"location":"rt/","title":"Rotten Tomatoes","text":""},{"location":"rt/#usage","title":"Usage","text":"

To access Rotten Tomatoes data points, first ensure you have loaded the Rotten Tomatoes source through:

await phylm.load_source(\"rt\")\n

Alternatively you can instantiate the Rotten Tomatoes source class directly through:

from phylm.sources import Rt\n\nrot_tom = Rt(raw_title=\"The Matrix\", raw_year=1999) \u00a0# raw_year is optional\nawait rot_tom.load_source()\n
"},{"location":"rt/#reference","title":"Reference","text":"

Class to abstract a Rotten Tomatoes result.

"},{"location":"rt/#phylm.sources.rt.Rt.title","title":"title: Optional[str] property","text":"

Return the title.

Returns:

Type Description Optional[str]

the title of the movie

"},{"location":"rt/#phylm.sources.rt.Rt.tomato_score","title":"tomato_score: Optional[str] property","text":"

Return the Tomatometer Score.

Returns:

Type Description Optional[str]

the tomatometer score

"},{"location":"rt/#phylm.sources.rt.Rt.year","title":"year: Optional[str] property","text":"

Return the year.

Returns:

Type Description Optional[str]

the year of the movie

"},{"location":"rt/#phylm.sources.rt.Rt.__init__","title":"__init__(raw_title: str, raw_year: Optional[int] = None) -> None","text":"

Initialize the object.

Parameters:

Name Type Description Default raw_title str

the given title of the movie

required raw_year Optional[int]

an optional year for improved matching

None"},{"location":"rt/#phylm.sources.rt.Rt.load_source","title":"load_source(session: Optional[ClientSession] = None) -> None async","text":"

Asynchronously load the data from the source.

Parameters:

Name Type Description Default session Optional[ClientSession]

an optional instance of aiohttp.ClientSession in which to run the request

None"},{"location":"tmdb/","title":"TMDB","text":""},{"location":"tmdb/#usage","title":"Usage","text":"

To access TMDB data points, first ensure you have loaded the TMDB source through:

await phylm.load_source(\"tmdb\")\n

Alternatively you can instantiate the TMDB source class directly through:

from phylm.sources import Tmdb\n\ntmdb = Tmdb(raw_title=\"The Matrix\", raw_year=1999) \u00a0# raw_year is optional\nawait tmdb.load_source()\n
"},{"location":"tmdb/#movie-id","title":"Movie ID","text":"

If you know the TMDB movie ID you can instantiate the Phylm class with a tmdb_id property:

from phylm.sources import Tmdb\n\ntmdb = Tmdb(raw_title=\"The Matrix\", tmdb_id=\"609\")\n

Then, when running load_source for tmdb, phylm will first perform a search based on the ID. If the ID is valid the result will be selected, if not then it will fall back to a title search.

Alternatively, you can pass it to load_source with \"tmdb\" as the first argument:

await phylm.load_source(\"tmdb\", tmdb_id=\"609\")\n

Or instantiate the TMDB source class with the ID:

from phylm.sources import Tmdb\n\ntmdb = Tmdb(movie_id=\"0133093\")\n

If instantiating the class directly you must supply at least one of movie_id or raw_title, otherwise a ValueError will be raised.

Note that TMDB doesn't provide any fuzzy search for title, only exact matches are returned.

"},{"location":"tmdb/#reference","title":"Reference","text":"

Class to abstract a TMDB result.

"},{"location":"tmdb/#phylm.sources.tmdb.Tmdb.id","title":"id: Optional[str] property","text":"

Return the TMDB id.

Returns:

Type Description Optional[str]

the id of the movie

"},{"location":"tmdb/#phylm.sources.tmdb.Tmdb.imdb_id","title":"imdb_id: Optional[str] property","text":"

Return the IMDb id.

Returns:

Type Description Optional[str]

the IMDb id of the movie

"},{"location":"tmdb/#phylm.sources.tmdb.Tmdb.plot","title":"plot: Optional[str] property","text":"

Return the plot.

Returns:

Type Description Optional[str]

the plot of the movie

"},{"location":"tmdb/#phylm.sources.tmdb.Tmdb.rating","title":"rating: Optional[float] property","text":"

Return the TMDB rating.

Returns:

Type Description Optional[float]

the rating of the movie

"},{"location":"tmdb/#phylm.sources.tmdb.Tmdb.release_date","title":"release_date: Optional[str] property","text":"

Return the movie's release_date.

Returns:

Type Description Optional[str]

the release date of the movie

"},{"location":"tmdb/#phylm.sources.tmdb.Tmdb.runtime","title":"runtime: Optional[int] property","text":"

Return the runtime.

Returns:

Type Description Optional[int]

the runtime of the movie

"},{"location":"tmdb/#phylm.sources.tmdb.Tmdb.title","title":"title: Optional[str] property","text":"

Return the TMDB title.

Returns:

Type Description Optional[str]

the title of the movie

"},{"location":"tmdb/#phylm.sources.tmdb.Tmdb.year","title":"year: Optional[int] property","text":"

Return the movie's year.

Returns:

Type Description Optional[int]

the year the movie was made

"},{"location":"tmdb/#phylm.sources.tmdb.Tmdb.__init__","title":"__init__(raw_title: Optional[str] = None, movie_id: Optional[str] = None, raw_year: Optional[int] = None, api_key: Optional[str] = None, session: Optional[ClientSession] = None) -> None","text":"

Initialize the object.

Note that at least one of raw_title or movie_id must be given to be used as a search term. movie_id is preferred over raw_title.

Parameters:

Name Type Description Default raw_title Optional[str]

the title of the movie. Note that TMDB doesn't support fuzzy search.

None movie_id Optional[str]

the TMDB id of the movie.

None raw_year Optional[int]

an optional year for improved matching if only title is given.

None api_key Optional[str]

a TMDB api key. Must be supplied here or as an env var

None session Optional[ClientSession]

a aiohttp.ClientSession instance. One will be created if not supplied.

None

Raises:

Type Description ValueError

if neither raw_title nor movie_id is supplied.

"},{"location":"tmdb/#phylm.sources.tmdb.Tmdb.genres","title":"genres(limit: int = 3) -> List[str]","text":"

Return the genres.

Parameters:

Name Type Description Default limit int

an optional number of genres to return

3

Returns:

Type Description List[str]

a list of the movie's genres

"},{"location":"tmdb/#phylm.sources.tmdb.Tmdb.load_source","title":"load_source(session: Optional[ClientSession] = None) -> None async","text":"

Asynchronously load the data for from the source.

Parameters:

Name Type Description Default session Optional[ClientSession]

an optional aiohttp.ClientSession instance

None"},{"location":"tools/","title":"Tools","text":"

phylm also offers some tools and utilities related to movies.

"},{"location":"tools/#search-movies","title":"Search movies","text":"

For a given movie title query you can return a list of search results from IMDb through search_movies:

>>> from phylm.tools import search_movies\n>>> search_movies(\"the matrix\")\n[{\n  'title': 'The Matrix',\n  'kind': 'movie',\n  'year': 1999,\n  'cover_photo': 'https://some-url.com',\n  'imdb_id': '0133093',\n}, {\n  'title': 'The Matrix Reloaded',\n  'kind': 'movie',\n  'year': 2003,\n  'cover_photo': 'https://some-url.com',\n  'imdb_id': '0234215',\n}, {\n...\n
"},{"location":"tools/#phylm.tools.search_movies","title":"phylm.tools.search_movies(query: str) -> List[Dict[str, Union[str, int]]]","text":"

Return a list of search results for a query.

Parameters:

Name Type Description Default query str

the search query

required

Returns:

Type Description List[Dict[str, Union[str, int]]]

a list of search results

"},{"location":"tools/#tmdb","title":"TMDB","text":"

phylm also provides tools to interact with The Movie Database (TMDb).

To use TMDb tools you'll need to sign up for an API key, instructions here. Once you have your key, export it as an env var called TMDB_API_KEY so that it's available to use in these tools. You also have the option of passing in the key as an argument to each function.

"},{"location":"tools/#search-movies_1","title":"Search movies","text":"

For a given movie title query you can return a list of search results from TMDb through search_tmdb_movies. Note that this search performs a lot quicker than the imdb search_movies.

>>> from phylm.tools import search_tmdb_movies\n>>> search_tmdb_movies(\"The Matrix\", api_key=\"abc\") #\u00a0the api key can be provided as an env var instead\n[{\n  'adult': False,\n  'backdrop_path': '/fNG7i7RqMErkcqhohV2a6cV1Ehy.jpg',\n  'genre_ids': [28, 878],\n  'id': 603,\n  'original_language': 'en',\n  'original_title': 'The Matrix',\n  'overview': 'Set in the 22nd century, The Matrix tells the story of a computer hacker...'\n  'popularity': 79.956,\n  'poster_path': '/f89U3ADr1oiB1s9GkdPOEpXUk5H.jpg',\n  'release_date': '1999-03-30',\n  'title': 'The Matrix',\n  'video': False,\n  'vote_average': 8.2,\n  'vote_count': 20216,\n}, {\n  ...\n}\n

By default the release_date will be the US release date. You can specify a different region by providing a region argument:

>>> from phylm.tools import search_tmdb_movies\n>>> search_tmdb_movies(\"The Matrix\", region=\"gb\")\n[{\n  'id': 603,\n  ...\n  'release_date': '1999-06-11',\n  'title': 'The Matrix',\n  ...\n}, {\n  ...\n}\n
"},{"location":"tools/#phylm.tools.search_tmdb_movies","title":"phylm.tools.search_tmdb_movies(query: str, api_key: Optional[str] = None, region: Optional[str] = None) -> List[Dict[str, Any]]","text":"

Search for movies on TMDb.

Parameters:

Name Type Description Default query str

the query string

required api_key Optional[str]

an api_key can either be provided here or through a TMDB_API_KEY env var

None region Optional[str]

an optional region to provide with the search request, affects the release_date value returned, must be provided in ISO 3166-1 format (eg. \"us\" or \"gb\")

None

Returns:

Type Description List[Dict[str, Any]]

List[Dict[str, Any]]: the search results

"},{"location":"tools/#get-streaming-providers","title":"Get streaming providers","text":"

For a given movie TMDb id and list of regions, you can return a list of streaming providers from TMDb via Just Watch through get_streaming_providers.

>>> from phylm.tools import get_streaming_providers\n>>> get_streaming_providers(tmdb_movie_id=\"438631\", regions=[\"gb\"], api_key=\"abc\")\n{\n  'gb': {\n    'link': 'https://www.themoviedb.org/movie/438631-dune/watch?locale=GB',\n    'rent': [{\n      'display_priority': 8,\n      'logo_path': '/pZgeSWpfvD59x6sY6stT5c6uc2h.jpg',\n      'provider_id': 130,\n      'provider_name': 'Sky Store',\n    }],\n  },\n}\n

Consult the TMDb docs for more information on the data that's returned.

"},{"location":"tools/#phylm.tools.get_streaming_providers","title":"phylm.tools.get_streaming_providers(tmdb_movie_id: str, regions: List[str], api_key: Optional[str] = None) -> Dict[str, Any]","text":"

Return a list of streaming providers for a given movie.

Parameters:

Name Type Description Default tmdb_movie_id str

the tmdb id of the movie

required regions List[str]

a list of regions to trim down the return list

required api_key Optional[str]

an api_key can either be provided here or through a TMDB_API_KEY env var

None

Returns:

Type Description Dict[str, Any]

Dict[str, Any]: a dictionary of streaming providers, keyed by region name

"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000..7c3dd51 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,43 @@ + + + + https://dbatten5.github.io/phylm/ + 2023-10-18 + daily + + + https://dbatten5.github.io/phylm/contributing/ + 2023-10-18 + daily + + + https://dbatten5.github.io/phylm/imdb/ + 2023-10-18 + daily + + + https://dbatten5.github.io/phylm/mtc/ + 2023-10-18 + daily + + + https://dbatten5.github.io/phylm/phylm/ + 2023-10-18 + daily + + + https://dbatten5.github.io/phylm/rt/ + 2023-10-18 + daily + + + https://dbatten5.github.io/phylm/tmdb/ + 2023-10-18 + daily + + + https://dbatten5.github.io/phylm/tools/ + 2023-10-18 + daily + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 0000000..803ceff Binary files /dev/null and b/sitemap.xml.gz differ diff --git a/tmdb/index.html b/tmdb/index.html new file mode 100644 index 0000000..8ba25c4 --- /dev/null +++ b/tmdb/index.html @@ -0,0 +1,13 @@ + TMDB - Phylm

TMDB

Usage

To access TMDB data points, first ensure you have loaded the TMDB source through:

await phylm.load_source("tmdb")
+

Alternatively you can instantiate the TMDB source class directly through:

from phylm.sources import Tmdb
+
+tmdb = Tmdb(raw_title="The Matrix", raw_year=1999)  # raw_year is optional
+await tmdb.load_source()
+

Movie ID

If you know the TMDB movie ID you can instantiate the Phylm class with a tmdb_id property:

from phylm.sources import Tmdb
+
+tmdb = Tmdb(raw_title="The Matrix", tmdb_id="609")
+

Then, when running load_source for tmdb, phylm will first perform a search based on the ID. If the ID is valid the result will be selected, if not then it will fall back to a title search.

Alternatively, you can pass it to load_source with "tmdb" as the first argument:

await phylm.load_source("tmdb", tmdb_id="609")
+

Or instantiate the TMDB source class with the ID:

from phylm.sources import Tmdb
+
+tmdb = Tmdb(movie_id="0133093")
+

If instantiating the class directly you must supply at least one of movie_id or raw_title, otherwise a ValueError will be raised.

Note that TMDB doesn't provide any fuzzy search for title, only exact matches are returned.

Reference

Class to abstract a TMDB result.

id: Optional[str] property

Return the TMDB id.

Returns:

Type Description
Optional[str]

the id of the movie

imdb_id: Optional[str] property

Return the IMDb id.

Returns:

Type Description
Optional[str]

the IMDb id of the movie

plot: Optional[str] property

Return the plot.

Returns:

Type Description
Optional[str]

the plot of the movie

rating: Optional[float] property

Return the TMDB rating.

Returns:

Type Description
Optional[float]

the rating of the movie

release_date: Optional[str] property

Return the movie's release_date.

Returns:

Type Description
Optional[str]

the release date of the movie

runtime: Optional[int] property

Return the runtime.

Returns:

Type Description
Optional[int]

the runtime of the movie

title: Optional[str] property

Return the TMDB title.

Returns:

Type Description
Optional[str]

the title of the movie

year: Optional[int] property

Return the movie's year.

Returns:

Type Description
Optional[int]

the year the movie was made

__init__(raw_title: Optional[str] = None, movie_id: Optional[str] = None, raw_year: Optional[int] = None, api_key: Optional[str] = None, session: Optional[ClientSession] = None) -> None

Initialize the object.

Note that at least one of raw_title or movie_id must be given to be used as a search term. movie_id is preferred over raw_title.

Parameters:

Name Type Description Default
raw_title Optional[str]

the title of the movie. Note that TMDB doesn't support fuzzy search.

None
movie_id Optional[str]

the TMDB id of the movie.

None
raw_year Optional[int]

an optional year for improved matching if only title is given.

None
api_key Optional[str]

a TMDB api key. Must be supplied here or as an env var

None
session Optional[ClientSession]

a aiohttp.ClientSession instance. One will be created if not supplied.

None

Raises:

Type Description
ValueError

if neither raw_title nor movie_id is supplied.

genres(limit: int = 3) -> List[str]

Return the genres.

Parameters:

Name Type Description Default
limit int

an optional number of genres to return

3

Returns:

Type Description
List[str]

a list of the movie's genres

load_source(session: Optional[ClientSession] = None) -> None async

Asynchronously load the data for from the source.

Parameters:

Name Type Description Default
session Optional[ClientSession]

an optional aiohttp.ClientSession instance

None

Last update: 2023-10-18
\ No newline at end of file diff --git a/tools/index.html b/tools/index.html new file mode 100644 index 0000000..18d5bb9 --- /dev/null +++ b/tools/index.html @@ -0,0 +1,61 @@ + Tools - Phylm

Tools

phylm also offers some tools and utilities related to movies.

Search movies

For a given movie title query you can return a list of search results from IMDb through search_movies:

>>> from phylm.tools import search_movies
+>>> search_movies("the matrix")
+[{
+  'title': 'The Matrix',
+  'kind': 'movie',
+  'year': 1999,
+  'cover_photo': 'https://some-url.com',
+  'imdb_id': '0133093',
+}, {
+  'title': 'The Matrix Reloaded',
+  'kind': 'movie',
+  'year': 2003,
+  'cover_photo': 'https://some-url.com',
+  'imdb_id': '0234215',
+}, {
+...
+

phylm.tools.search_movies(query: str) -> List[Dict[str, Union[str, int]]]

Return a list of search results for a query.

Parameters:

Name Type Description Default
query str

the search query

required

Returns:

Type Description
List[Dict[str, Union[str, int]]]

a list of search results

TMDB

phylm also provides tools to interact with The Movie Database (TMDb).

To use TMDb tools you'll need to sign up for an API key, instructions here. Once you have your key, export it as an env var called TMDB_API_KEY so that it's available to use in these tools. You also have the option of passing in the key as an argument to each function.

Search movies

For a given movie title query you can return a list of search results from TMDb through search_tmdb_movies. Note that this search performs a lot quicker than the imdb search_movies.

>>> from phylm.tools import search_tmdb_movies
+>>> search_tmdb_movies("The Matrix", api_key="abc") # the api key can be provided as an env var instead
+[{
+  'adult': False,
+  'backdrop_path': '/fNG7i7RqMErkcqhohV2a6cV1Ehy.jpg',
+  'genre_ids': [28, 878],
+  'id': 603,
+  'original_language': 'en',
+  'original_title': 'The Matrix',
+  'overview': 'Set in the 22nd century, The Matrix tells the story of a computer hacker...'
+  'popularity': 79.956,
+  'poster_path': '/f89U3ADr1oiB1s9GkdPOEpXUk5H.jpg',
+  'release_date': '1999-03-30',
+  'title': 'The Matrix',
+  'video': False,
+  'vote_average': 8.2,
+  'vote_count': 20216,
+}, {
+  ...
+}
+

By default the release_date will be the US release date. You can specify a different region by providing a region argument:

>>> from phylm.tools import search_tmdb_movies
+>>> search_tmdb_movies("The Matrix", region="gb")
+[{
+  'id': 603,
+  ...
+  'release_date': '1999-06-11',
+  'title': 'The Matrix',
+  ...
+}, {
+  ...
+}
+

phylm.tools.search_tmdb_movies(query: str, api_key: Optional[str] = None, region: Optional[str] = None) -> List[Dict[str, Any]]

Search for movies on TMDb.

Parameters:

Name Type Description Default
query str

the query string

required
api_key Optional[str]

an api_key can either be provided here or through a TMDB_API_KEY env var

None
region Optional[str]

an optional region to provide with the search request, affects the release_date value returned, must be provided in ISO 3166-1 format (eg. "us" or "gb")

None

Returns:

Type Description
List[Dict[str, Any]]

List[Dict[str, Any]]: the search results

Get streaming providers

For a given movie TMDb id and list of regions, you can return a list of streaming providers from TMDb via Just Watch through get_streaming_providers.

>>> from phylm.tools import get_streaming_providers
+>>> get_streaming_providers(tmdb_movie_id="438631", regions=["gb"], api_key="abc")
+{
+  'gb': {
+    'link': 'https://www.themoviedb.org/movie/438631-dune/watch?locale=GB',
+    'rent': [{
+      'display_priority': 8,
+      'logo_path': '/pZgeSWpfvD59x6sY6stT5c6uc2h.jpg',
+      'provider_id': 130,
+      'provider_name': 'Sky Store',
+    }],
+  },
+}
+

Consult the TMDb docs for more information on the data that's returned.

phylm.tools.get_streaming_providers(tmdb_movie_id: str, regions: List[str], api_key: Optional[str] = None) -> Dict[str, Any]

Return a list of streaming providers for a given movie.

Parameters:

Name Type Description Default
tmdb_movie_id str

the tmdb id of the movie

required
regions List[str]

a list of regions to trim down the return list

required
api_key Optional[str]

an api_key can either be provided here or through a TMDB_API_KEY env var

None

Returns:

Type Description
Dict[str, Any]

Dict[str, Any]: a dictionary of streaming providers, keyed by region name


Last update: 2023-10-18
\ No newline at end of file