From 11c139339f67fe6bd5f8416ea1017da03980256b Mon Sep 17 00:00:00 2001 From: mitsuhiko Date: Wed, 6 Mar 2024 17:45:02 +0000 Subject: [PATCH] Deployed 39f2c04 with MkDocs version: 1.4.3 --- .nojekyll | 0 404.html | 1388 ++++ CNAME | 1 + assets/images/favicon.png | Bin 0 -> 1870 bytes assets/javascripts/bundle.c2be25ad.min.js | 29 + assets/javascripts/bundle.c2be25ad.min.js.map | 8 + assets/javascripts/lunr/min/lunr.ar.min.js | 1 + assets/javascripts/lunr/min/lunr.da.min.js | 18 + assets/javascripts/lunr/min/lunr.de.min.js | 18 + assets/javascripts/lunr/min/lunr.du.min.js | 18 + assets/javascripts/lunr/min/lunr.es.min.js | 18 + assets/javascripts/lunr/min/lunr.fi.min.js | 18 + assets/javascripts/lunr/min/lunr.fr.min.js | 18 + assets/javascripts/lunr/min/lunr.hi.min.js | 1 + assets/javascripts/lunr/min/lunr.hu.min.js | 18 + assets/javascripts/lunr/min/lunr.hy.min.js | 1 + assets/javascripts/lunr/min/lunr.it.min.js | 18 + assets/javascripts/lunr/min/lunr.ja.min.js | 1 + assets/javascripts/lunr/min/lunr.jp.min.js | 1 + assets/javascripts/lunr/min/lunr.kn.min.js | 1 + assets/javascripts/lunr/min/lunr.ko.min.js | 1 + assets/javascripts/lunr/min/lunr.multi.min.js | 1 + assets/javascripts/lunr/min/lunr.nl.min.js | 18 + assets/javascripts/lunr/min/lunr.no.min.js | 18 + assets/javascripts/lunr/min/lunr.pt.min.js | 18 + assets/javascripts/lunr/min/lunr.ro.min.js | 18 + assets/javascripts/lunr/min/lunr.ru.min.js | 18 + assets/javascripts/lunr/min/lunr.sa.min.js | 1 + .../lunr/min/lunr.stemmer.support.min.js | 1 + assets/javascripts/lunr/min/lunr.sv.min.js | 18 + assets/javascripts/lunr/min/lunr.ta.min.js | 1 + assets/javascripts/lunr/min/lunr.te.min.js | 1 + assets/javascripts/lunr/min/lunr.th.min.js | 1 + assets/javascripts/lunr/min/lunr.tr.min.js | 18 + assets/javascripts/lunr/min/lunr.vi.min.js | 1 + assets/javascripts/lunr/min/lunr.zh.min.js | 1 + assets/javascripts/lunr/tinyseg.js | 206 + assets/javascripts/lunr/wordcut.js | 6708 +++++++++++++++++ .../workers/search.208ed371.min.js | 42 + .../workers/search.208ed371.min.js.map | 8 + assets/stylesheets/main.85bb2934.min.css | 1 + assets/stylesheets/main.85bb2934.min.css.map | 1 + assets/stylesheets/palette.a6bdf11c.min.css | 1 + .../stylesheets/palette.a6bdf11c.min.css.map | 1 + changelog/index.html | 2532 +++++++ community/index.html | 1522 ++++ get | 82 + guide/basics/index.html | 1655 ++++ guide/commands/add/index.html | 1599 ++++ guide/commands/build/index.html | 1567 ++++ guide/commands/config/index.html | 1556 ++++ guide/commands/fetch/index.html | 1549 ++++ guide/commands/fmt/index.html | 1578 ++++ guide/commands/index.html | 1489 ++++ guide/commands/init/index.html | 1574 ++++ guide/commands/install/index.html | 1594 ++++ guide/commands/lint/index.html | 1570 ++++ guide/commands/list/index.html | 1435 ++++ guide/commands/lock/index.html | 1554 ++++ guide/commands/make-req/index.html | 1553 ++++ guide/commands/pin/index.html | 1551 ++++ guide/commands/publish/index.html | 1564 ++++ guide/commands/remove/index.html | 1551 ++++ guide/commands/run/index.html | 1541 ++++ guide/commands/self/completion/index.html | 1529 ++++ guide/commands/self/index.html | 1479 ++++ guide/commands/self/uninstall/index.html | 1531 ++++ guide/commands/self/update/index.html | 1545 ++++ guide/commands/show/index.html | 1537 ++++ guide/commands/sync/index.html | 1572 ++++ guide/commands/toolchain/fetch/index.html | 1551 ++++ guide/commands/toolchain/index.html | 1482 ++++ guide/commands/toolchain/list/index.html | 1541 ++++ guide/commands/toolchain/register/index.html | 1535 ++++ guide/commands/toolchain/remove/index.html | 1526 ++++ guide/commands/tools/index.html | 1479 ++++ guide/commands/tools/install/index.html | 1596 ++++ guide/commands/tools/list/index.html | 1543 ++++ guide/commands/tools/uninstall/index.html | 1535 ++++ guide/commands/uninstall/index.html | 1533 ++++ guide/commands/version/index.html | 1538 ++++ guide/config/index.html | 1654 ++++ guide/deps/index.html | 1552 ++++ guide/faq/index.html | 1727 +++++ guide/index.html | 1481 ++++ guide/installation/index.html | 1859 +++++ guide/publish/index.html | 1561 ++++ guide/pyproject/index.html | 1733 +++++ guide/rust/index.html | 1539 ++++ guide/shims/index.html | 1526 ++++ guide/sources/index.html | 1655 ++++ guide/sync/index.html | 1631 ++++ guide/toolchains/cpython/index.html | 1557 ++++ guide/toolchains/index.html | 1619 ++++ guide/toolchains/pypy/index.html | 1531 ++++ guide/tools/index.html | 1556 ++++ guide/virtual/index.html | 1534 ++++ guide/workspaces/index.html | 1534 ++++ hooks.py | 7 + index.html | 1530 ++++ philosophy/index.html | 1879 +++++ search/search_index.json | 1 + sitemap.xml | 3 + sitemap.xml.gz | Bin 0 -> 127 bytes static/banner-dark.png | Bin 0 -> 40057 bytes static/banner.png | Bin 0 -> 42371 bytes static/extra.css | 104 + static/favicon.svg | 14 + static/logo-auto.svg | 14 + static/logo.svg | 1 + 110 files changed, 96149 insertions(+) create mode 100644 .nojekyll create mode 100644 404.html create mode 100644 CNAME create mode 100644 assets/images/favicon.png create mode 100644 assets/javascripts/bundle.c2be25ad.min.js create mode 100644 assets/javascripts/bundle.c2be25ad.min.js.map create mode 100644 assets/javascripts/lunr/min/lunr.ar.min.js create mode 100644 assets/javascripts/lunr/min/lunr.da.min.js create mode 100644 assets/javascripts/lunr/min/lunr.de.min.js create mode 100644 assets/javascripts/lunr/min/lunr.du.min.js create mode 100644 assets/javascripts/lunr/min/lunr.es.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.fr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hu.min.js create mode 100644 assets/javascripts/lunr/min/lunr.hy.min.js create mode 100644 assets/javascripts/lunr/min/lunr.it.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ja.min.js create mode 100644 assets/javascripts/lunr/min/lunr.jp.min.js create mode 100644 assets/javascripts/lunr/min/lunr.kn.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ko.min.js create mode 100644 assets/javascripts/lunr/min/lunr.multi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.nl.min.js create mode 100644 assets/javascripts/lunr/min/lunr.no.min.js create mode 100644 assets/javascripts/lunr/min/lunr.pt.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ro.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ru.min.js create mode 100644 assets/javascripts/lunr/min/lunr.sa.min.js create mode 100644 assets/javascripts/lunr/min/lunr.stemmer.support.min.js create mode 100644 assets/javascripts/lunr/min/lunr.sv.min.js create mode 100644 assets/javascripts/lunr/min/lunr.ta.min.js create mode 100644 assets/javascripts/lunr/min/lunr.te.min.js create mode 100644 assets/javascripts/lunr/min/lunr.th.min.js create mode 100644 assets/javascripts/lunr/min/lunr.tr.min.js create mode 100644 assets/javascripts/lunr/min/lunr.vi.min.js create mode 100644 assets/javascripts/lunr/min/lunr.zh.min.js create mode 100644 assets/javascripts/lunr/tinyseg.js create mode 100644 assets/javascripts/lunr/wordcut.js create mode 100644 assets/javascripts/workers/search.208ed371.min.js create mode 100644 assets/javascripts/workers/search.208ed371.min.js.map create mode 100644 assets/stylesheets/main.85bb2934.min.css create mode 100644 assets/stylesheets/main.85bb2934.min.css.map create mode 100644 assets/stylesheets/palette.a6bdf11c.min.css create mode 100644 assets/stylesheets/palette.a6bdf11c.min.css.map create mode 100644 changelog/index.html create mode 100644 community/index.html create mode 100755 get create mode 100644 guide/basics/index.html create mode 100644 guide/commands/add/index.html create mode 100644 guide/commands/build/index.html create mode 100644 guide/commands/config/index.html create mode 100644 guide/commands/fetch/index.html create mode 100644 guide/commands/fmt/index.html create mode 100644 guide/commands/index.html create mode 100644 guide/commands/init/index.html create mode 100644 guide/commands/install/index.html create mode 100644 guide/commands/lint/index.html create mode 100644 guide/commands/list/index.html create mode 100644 guide/commands/lock/index.html create mode 100644 guide/commands/make-req/index.html create mode 100644 guide/commands/pin/index.html create mode 100644 guide/commands/publish/index.html create mode 100644 guide/commands/remove/index.html create mode 100644 guide/commands/run/index.html create mode 100644 guide/commands/self/completion/index.html create mode 100644 guide/commands/self/index.html create mode 100644 guide/commands/self/uninstall/index.html create mode 100644 guide/commands/self/update/index.html create mode 100644 guide/commands/show/index.html create mode 100644 guide/commands/sync/index.html create mode 100644 guide/commands/toolchain/fetch/index.html create mode 100644 guide/commands/toolchain/index.html create mode 100644 guide/commands/toolchain/list/index.html create mode 100644 guide/commands/toolchain/register/index.html create mode 100644 guide/commands/toolchain/remove/index.html create mode 100644 guide/commands/tools/index.html create mode 100644 guide/commands/tools/install/index.html create mode 100644 guide/commands/tools/list/index.html create mode 100644 guide/commands/tools/uninstall/index.html create mode 100644 guide/commands/uninstall/index.html create mode 100644 guide/commands/version/index.html create mode 100644 guide/config/index.html create mode 100644 guide/deps/index.html create mode 100644 guide/faq/index.html create mode 100644 guide/index.html create mode 100644 guide/installation/index.html create mode 100644 guide/publish/index.html create mode 100644 guide/pyproject/index.html create mode 100644 guide/rust/index.html create mode 100644 guide/shims/index.html create mode 100644 guide/sources/index.html create mode 100644 guide/sync/index.html create mode 100644 guide/toolchains/cpython/index.html create mode 100644 guide/toolchains/index.html create mode 100644 guide/toolchains/pypy/index.html create mode 100644 guide/tools/index.html create mode 100644 guide/virtual/index.html create mode 100644 guide/workspaces/index.html create mode 100644 hooks.py create mode 100644 index.html create mode 100644 philosophy/index.html create mode 100644 search/search_index.json create mode 100644 sitemap.xml create mode 100644 sitemap.xml.gz create mode 100644 static/banner-dark.png create mode 100644 static/banner.png create mode 100644 static/extra.css create mode 100644 static/favicon.svg create mode 100644 static/logo-auto.svg create mode 100644 static/logo.svg diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000000..e69de29bb2 diff --git a/404.html b/404.html new file mode 100644 index 0000000000..b938425c30 --- /dev/null +++ b/404.html @@ -0,0 +1,1388 @@ + + + + + + + + + + + + + + + + + + + + Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ +

404 - Not found

+ +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 0000000000..ced6063925 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +rye-up.com diff --git a/assets/images/favicon.png b/assets/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..1cf13b9f9d978896599290a74f77d5dbe7d1655c GIT binary patch literal 1870 zcmV-U2eJ5xP)Gc)JR9QMau)O=X#!i9;T z37kk-upj^(fsR36MHs_+1RCI)NNu9}lD0S{B^g8PN?Ww(5|~L#Ng*g{WsqleV}|#l zz8@ri&cTzw_h33bHI+12+kK6WN$h#n5cD8OQt`5kw6p~9H3()bUQ8OS4Q4HTQ=1Ol z_JAocz`fLbT2^{`8n~UAo=#AUOf=SOq4pYkt;XbC&f#7lb$*7=$na!mWCQ`dBQsO0 zLFBSPj*N?#u5&pf2t4XjEGH|=pPQ8xh7tpx;US5Cx_Ju;!O`ya-yF`)b%TEt5>eP1ZX~}sjjA%FJF?h7cX8=b!DZl<6%Cv z*G0uvvU+vmnpLZ2paivG-(cd*y3$hCIcsZcYOGh{$&)A6*XX&kXZd3G8m)G$Zz-LV z^GF3VAW^Mdv!)4OM8EgqRiz~*Cji;uzl2uC9^=8I84vNp;ltJ|q-*uQwGp2ma6cY7 z;`%`!9UXO@fr&Ebapfs34OmS9^u6$)bJxrucutf>`dKPKT%%*d3XlFVKunp9 zasduxjrjs>f8V=D|J=XNZp;_Zy^WgQ$9WDjgY=z@stwiEBm9u5*|34&1Na8BMjjgf3+SHcr`5~>oz1Y?SW^=K z^bTyO6>Gar#P_W2gEMwq)ot3; zREHn~U&Dp0l6YT0&k-wLwYjb?5zGK`W6S2v+K>AM(95m2C20L|3m~rN8dprPr@t)5lsk9Hu*W z?pS990s;Ez=+Rj{x7p``4>+c0G5^pYnB1^!TL=(?HLHZ+HicG{~4F1d^5Awl_2!1jICM-!9eoLhbbT^;yHcefyTAaqRcY zmuctDopPT!%k+}x%lZRKnzykr2}}XfG_ne?nRQO~?%hkzo;@RN{P6o`&mMUWBYMTe z6i8ChtjX&gXl`nvrU>jah)2iNM%JdjqoaeaU%yVn!^70x-flljp6Q5tK}5}&X8&&G zX3fpb3E(!rH=zVI_9Gjl45w@{(ITqngWFe7@9{mX;tO25Z_8 zQHEpI+FkTU#4xu>RkN>b3Tnc3UpWzPXWm#o55GKF09j^Mh~)K7{QqbO_~(@CVq! zS<8954|P8mXN2MRs86xZ&Q4EfM@JB94b=(YGuk)s&^jiSF=t3*oNK3`rD{H`yQ?d; ztE=laAUoZx5?RC8*WKOj`%LXEkgDd>&^Q4M^z`%u0rg-It=hLCVsq!Z%^6eB-OvOT zFZ28TN&cRmgU}Elrnk43)!>Z1FCPL2K$7}gwzIc48NX}#!A1BpJP?#v5wkNprhV** z?Cpalt1oH&{r!o3eSKc&ap)iz2BTn_VV`4>9M^b3;(YY}4>#ML6{~(4mH+?%07*qo IM6N<$f(jP3KmY&$ literal 0 HcmV?d00001 diff --git a/assets/javascripts/bundle.c2be25ad.min.js b/assets/javascripts/bundle.c2be25ad.min.js new file mode 100644 index 0000000000..f32333ee14 --- /dev/null +++ b/assets/javascripts/bundle.c2be25ad.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){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){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(` + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Changelog

+

Here you can find all the released changes to Rye. If you want to also see +the in-development changes that were not released yet, refer to the +CHANGELOG.md file +in the repository.

+ + +

0.27.0

+

Released on 2024-02-26

+
    +
  • +

    rye now uses uv to bootstrap its internal packages and tools. #754

    +
  • +
  • +

    rye no longer fails if an incorrect VIRTUAL_ENV environment + variable is exported. #766

    +
  • +
  • +

    Added latest Python builds. #771

    +
  • +
  • +

    When uv is used the prompt is now set to the project name. #773

    +
  • +
  • +

    Allow rye fetch --force to force re-fetch a downloaded toolchain. #778

    +
  • +
  • +

    Fixed a panic when adding a package to a virtual project. #783

    +
  • +
  • +

    Bumped uv to 0.1.11. #790

    +
  • +
+

0.26.0

+

Released on 2024-02-23

+
    +
  • +

    init now supports --script and --lib to generate a script or library project. #738

    +
  • +
  • +

    Fixed rye config --show-path abort with an error. #706

    +
  • +
  • +

    Bumped uv to 0.1.9. #719, #740, #746

    +
  • +
  • +

    Bumped ruff to 0.2.2. #700

    +
  • +
  • +

    Prevent rye toolchain remove from removing the currently active toolchain. #693

    +
  • +
  • +

    Sync latest PyPy releases. #683

    +
  • +
  • +

    Fixes an issue where when uv is enabled, add did not honor custom sources. #720

    +
  • +
  • +

    When uv is enabled, rye will now automatically sync on add and remove. #677

    +
  • +
  • +

    Rename rye tools list flags: -i, --include-scripts to -s, --include-scripts and -v, --version-show to -v, --include-version. #722

    +
  • +
+

0.25.0

+

Released on 2024-02-19

+
    +
  • +

    Improved the error message if config is invoked without arguments. #660

    +
  • +
  • +

    Bump uv to 0.1.5. #665, #675, #698

    +
  • +
  • +

    When uv is enabled, rye add now uses uv instead of unearth + internally. #667

    +
  • +
  • +

    The installer now has slightly better wording for what the shims are doing. #669

    +
  • +
  • +

    uv can now also be enabled on windows. #675

    +
  • +
  • +

    Removed the unsupported and un-used arch parameter from fetch. #681

    +
  • +
  • +

    Fixed the -q parameter not working for the init command. #686

    +
  • +
  • +

    rye tools list shows broken tools if the toolchain was removed. #692

    +
  • +
  • +

    Configure the ruff cache directory to be located within the workspace root. #689

    +
  • +
  • +

    Use default toolchain to install tools. #666

    +
  • +
  • +

    rye --version now shows if uv is enabled. #699

    +
  • +
+

0.24.0

+

Released on 2024-02-15

+
    +
  • +

    Added new rye list command and deprecated rye show --installed-deps which it replaces. #656

    +
  • +
  • +

    Added experimental support for uv. #657

    +
  • +
+

0.23.0

+

Released on 2024-02-13

+
    +
  • +

    When behavior.venv-mark-sync-ignore is set to false and the file system + does not support extended attributes, no longer will a warning be printed. #633

    +
  • +
  • +

    Fixed a bug that caused warnings about unsupported operations to be shown on Linux. #634

    +
  • +
  • +

    The venv sync marker is now only updated when a new virtualenv is created. #638

    +
  • +
  • +

    Lockfiles now contain annotations. #643

    +
  • +
+

0.22.0

+

Released on 2024-02-09

+
    +
  • +

    Virtual envs managed by Rye will now by default be marked to not sync to + known cloud storage systems (Dropbox and iCloud). #589

    +
  • +
  • +

    Fixed a bug where pip-tools sometimes did not get initialized. #596

    +
  • +
  • +

    Rye now prefers installed toolchains over newer latest toolchains unless + a precise pin is used. #598

    +
  • +
  • +

    Removed the non functional shell command. #602

    +
  • +
  • +

    Upgraded internal unearth dependency which resolved an issue where + rye add tensorflow would not work. #614

    +
  • +
  • +

    The installer now supports RYE_TOOLCHAIN_VERSION. #606

    +
  • +
  • +

    rye init will no longer create packages with leading digits. #616

    +
  • +
  • +

    Rye now statically links vcruntime on Windows which no longer requires + the vs redist to be installed. #622

    +
  • +
  • +

    rye show now prints out which sources are configured for a project. #631

    +
  • +
+

0.21.0

+

Released on 2024-02-03

+
    +
  • +

    rye fetch now is able to fetch impliciit version in all cases. Previously + global shims were not properly defaulted which required the user to be explicit + with the fetch request. #574

    +
  • +
  • +

    The rye installer now prompts for the default toolchain version if global shims + are enabled. #576

    +
  • +
  • +

    The internal Python version was bumped to 3.12. #576

    +
  • +
  • +

    The installer now can automatically add Rye to PATH on most UNIX environments. #580

    +
  • +
+

0.20.0

+

Released on 2024-02-01

+
    +
  • +

    Improved the error message when an update could not be performed because files + are in use. #550

    +
  • +
  • +

    Rye now supports virtual projects. These are themselves not installed into the + virtualenv but their dependencies are. #551

    +
  • +
  • +

    Update the Python internals (python external dependencies) to new versions. #553

    +
  • +
  • +

    Update to newer versions of pip tools. For Python 3.7 6.14.0 is used, for + new Python versions 7.3.0 is used. #554

    +
  • +
  • +

    Added rye fmt and rye lint commands to format and lint with + the help of Ruff. #555

    +
  • +
  • +

    Restore cursor state on Ctrl-C. This fixes some issues where in rare cases the + cursor would disappear even after shutting down rye. #564

    +
  • +
  • +

    Upon installation Rye now prompts if global shims should be enabled. #566

    +
  • +
  • +

    Add a warning about bugs to the shell command until the behavior has been + fixed. #567

    +
  • +
+

0.19.0

+

Released on 2024-01-21

+
    +
  • +

    Improved the behavior of rye fetch. When invoked without arguments it will now try to + fetch the version of the requested Python interpreter. Specifically this combining + pin and fetch work in a much simplified manner. #545

    +
  • +
  • +

    Fixed an issue where rye init would pin a much too specific version in the .python-version + file that is generated. #545

    +
  • +
  • +

    On Windows the PATH is now automatically adjusted on install and uninstall. This means that + manually adding the rye folder to the search path is no longer necessary. #483

    +
  • +
  • +

    Fixed a regression in 0.18 that caused the add command to fail. #547

    +
  • +
+

0.18.0

+

Released on 2024-01-20

+
    +
  • +

    Incorporate new Python builds. #535

    +
  • +
  • +

    Disable revocation checks on windows to support corporate MITM proxies. #537

    +
  • +
  • +

    Detect when a virtualenv relocates and automatically re-create it on sync. #538

    +
  • +
  • +

    Added lock --with-sources, sync --with-sources and the new rye.tool.lock-with-sources + config. Passing this will ensure that source references are included in the + lock files. #540

    +
  • +
  • +

    When using global python shims, the .python-version file is now correctly + picked up in all cases. #541

    +
  • +
  • +

    Added a helpful message if someone attempts to run the non existing rye list + command. At a later point there should be a real listing command that can print + out the dependencies. Today the only option is the --installed-deps option on + the show command which spits out dependencies in the format of the lockfile. #543

    +
  • +
  • +

    The installer will no longer attempt to symlink targets which are not valid + executables on the platform. This works around some issues with Packages that + would prevent to install such as changedetection.io. #542

    +
  • +
+

0.17.0

+

Released on 2024-01-15

+
    +
  • +

    Fixed default generated script reference. #527

    +
  • +
  • +

    Correctly fall back to home folder if HOME is unset. #533

    +
  • +
+

0.16.0

+

Released on 2023-12-17

+
    +
  • +

    By default a script with the name of the project is now also configured. #519

    +
  • +
  • +

    Rye now configures hatchling better in rye init so that it works with + hatchling 1.19 and later. #521

    +
  • +
  • +

    Rye now detects the dummy Python shim that starts the windows store and + refuses to consider it. #486

    +
  • +
+

0.15.2

+

Released on 2023-10-04

+
    +
  • Fixed the updater not replacing the python shim correctly on Linux.
  • +
+

0.15.1

+

Released on 2023-10-03

+
    +
  • Fixed the updater not replacing the python3 shim correctly.
  • +
+

0.15.0

+

Released on 2023-10-03

+
    +
  • Added support for Python 3.12. #462
  • +
+

0.14.0

+

Released on 2023-10-01

+
    +
  • +

    Add support for fetching alternative CPU architectures. #447

    +
  • +
  • +

    The order of git submodule initialization was changed. This improves the + automatic author detection when includeIf is used. #443

    +
  • +
  • +

    The linux shim installer code will no longer fall back to symlinks when a + hardlink cannot be created. This is done as a symlinked shim will not + ever function correctly on Linux. This prevents the shim executables like + python to instead act as if they are rye. The fallback behavior is now + to copy the executable instead. #441

    +
  • +
  • +

    The installer now detects fish and will spit out additional instructions + for configuring the shell.

    +
  • +
  • +

    Fix the wrong behavior when bump version. #454

    +
  • +
+

0.13.0

+

Released on 2023-08-29

+
    +
  • +

    Add a python3 shim on windows. Previously entering python3 in the + command line would always bring up the windows store python proxy even + when global shims were enabled. As virtualenvs do not support the + python3 executable on windows, the internal shim handling is now also + changed so that trying to launch python3 will fall back to python. + This makes it possible to run maturin build.

    +
  • +
  • +

    Add maturin build command to start a new maturin PyO3 project.

    +
  • +
+

0.12.0

+

Released on 2023-08-27

+
    +
  • +

    Improve handling of the pth files for TCL on pypy. #409

    +
  • +
  • +

    The rye tools list command now accepts -v to also print out the + versions of the installed tools. #396

    +
  • +
  • +

    Fixed parsing of versions by rye version. #397

    +
  • +
  • +

    Improved the help message for rye init. #401

    +
  • +
  • +

    The email address now defaults to a syntactically valid email address + if not known to prevent errors with some build tools.

    +
  • +
  • +

    Added new Python versions.

    +
  • +
  • +

    The rye installer now detects NOEXEC temporary folders and prints out + a more helpful error message. #394

    +
  • +
  • +

    Fixed an issue where the author email was incorrectly detected. #382

    +
  • +
  • +

    The prompt of new virtualenvs is now set to the project name. #383

    +
  • +
+

0.11.0

+

Released on 2023-07-18

+
    +
  • +

    Added new Python versions.

    +
  • +
  • +

    Added a new config key default.author to configure the default author + that should be set. This overrides the default author that is normally + loaded from the git config. #377

    +
  • +
  • +

    When importing with rye init and no src folder exists, it will not be + created. #375

    +
  • +
  • +

    Added support for shell command on Windows. #363

    +
  • +
  • +

    Pin down pip to an older version to avoid issues with an incompatible + pip-tools version. This does not yet update pip-tools to 7.0 as there + are significant regressions in 7.x. #374

    +
  • +
  • +

    The version command can show dynamic versions now. #355

    +
  • +
  • +

    rye add now properly checks some incompatible argument combinations. #347

    +
  • +
  • +

    There is now more toolchain validation. This better supports cases where + rye was interrupted during sync. #351

    +
  • +
+

0.10.0

+

Released on 2023-07-07

+
    +
  • +

    Fixed a bug with rye init not operating correctly due to a argument conflict. #346

    +
  • +
  • +

    Scripts now support a PDM style call script type. #345

    +
  • +
  • +

    The init command is now capable of importing existing projects. #265

    +
  • +
  • +

    Fixed the global shim behavior on Windows. #344

    +
  • +
+

0.9.0

+

Released on 2023-06-21

+
    +
  • +

    The internal Rye Python version is now 3.11.

    +
  • +
  • +

    Rye now emits most messages, most of the time to stdout rather than stderr. #342

    +
  • +
  • +

    rye add now accepts --pin to let one override the type of pin to use. #341

    +
  • +
  • +

    Added rye config to read and manipulate the config.toml file. #339

    +
  • +
  • +

    Added support for the new behavior.global-python flag which turns on global + Python shimming. When enabled then the python shim works even outside of + Rye managed projects. Additionally the shim (when run outside of Rye managed + projects) supports a special first parameter +VERSION which requests a + specific version of Python (eg: python +3.8 to request Python 3.8). #336

    +
  • +
  • +

    Renamed the config key default.dependency_operator to default.dependency-operator + and behavior.force_rye_managed to behavior.force-rye-managed. #338

    +
  • +
+

0.8.0

+

Released on 2023-06-18

+
    +
  • +

    Rye for now prefers >= over ~= for newly added dependencies.

    +
  • +
  • +

    The workspace member declaration is now platform independent. If members is + now explicitly set to an empty list it will not fall back to auto discovery. #331

    +
  • +
  • +

    rye add now pins versions with == instead of ~= when the version of the + package does not use at least two components. This means that for instance it + will now correctly use openai-whisper==20230314 rather than + openai-whisper~=20230314 which is not actually satisfiable. #328

    +
  • +
  • +

    rye install now lets you install dependencies into the tool's virtualenv + during installation that are undeclared via the new --extra-requirement + option. #326

    +
  • +
  • +

    Improved handling of relative path installations by setting PROJECT_ROOT + the same way as PDM does. #321

    +
  • +
  • +

    Workspaces will now never discover pyproject.toml files in any dot + directories. (Name starting with .) #329

    +
  • +
  • +

    Fixed rye build not working correctly on Windows. #327

    +
  • +
+

0.7.0

+

Released on 2023-06-12

+
    +
  • +

    rye sync and rye lock now accept --pyproject. #296

    +
  • +
  • +

    Added JSON output to rye toolchain list by adding --format=json. #306

    +
  • +
  • +

    rye version can bump version by --bump option now. #298

    +
  • +
  • +

    Fixed members not handled correctly in workspaces. #300

    +
  • +
  • +

    Add --clean for build command. #297

    +
  • +
  • +

    Fixed an issue where pip was not invoked from the right working directory + causing issues for workspace installations. #292

    +
  • +
  • +

    rye init now accepts --private to set the Private :: Do Not Upload classifier + that prevents uploads to PyPI. #291

    +
  • +
+

0.6.0

+

Released on 2023-06-03

+
    +
  • +

    Add version subcommand for rye. #285

    +
  • +
  • +

    Fixed rye pin pinning the wrong version. #288

    +
  • +
  • +

    Calling rye init on the root directory no longer fails. #274

    +
  • +
  • +

    rye run, show, pin, shell and build now take a --pyproject + argument. #232

    +
  • +
+

0.5.0

+

Released on 2023-05-31

+
    +
  • +

    Rye will no longer enforce a downloaded interpreter for the internal + toolchain. If one has been registered that is compatible it will be + used. Additionally the installer now supports the RYE_TOOLCHAIN + environment variable which allows a user to supply an already existing + Python interpreter at install time. #267

    +
  • +
  • +

    The publish command now supports --yes to disable prompts. #270

    +
  • +
  • +

    When a Python debug build (Py_DEBUG) is registered as custom toolchain, + -dbg is automatically appended to the name by default. #269

    +
  • +
  • +

    lto+pgo builds are now preferred for the Python toolchain builds when + available. #268

    +
  • +
  • +

    It's now possible for .python-version to request partial Python versions + in which case the latest available is used. In particular this means that + a version like 3.10 can be written into .python-version rather than + 3.10.11. This can be accomplished by invoking pin with the new + --relaxed flag. #255

    +
  • +
  • +

    Workspaces will no longer discover pyproject.toml files in virtualenvs + or .git folders. #266

    +
  • +
  • +

    Adding or removing dependencies with add or remove now reformats + the dependencies array in the pyproject.toml file to multi-line + with trailing commas. This should result in significantly better + diffing behavior out of the box. #263

    +
  • +
  • +

    Default build-system and license can be specified in global config. #244

    +
  • +
  • +

    Fixed an issue where the init command would not let you create + flit based projects. #254

    +
  • +
  • +

    Resolve an error ("No such file or directory") shown after updates on + Linux machines. #252

    +
  • +
  • +

    The built-in updater now validates checksums of updates when updates have + SHA-256 hashes available. #253

    +
  • +
  • +

    init now accepts --no-pin to not create a .python-version file. #247

    +
  • +
+

0.4.0

+

Released on 2023-05-29

+
    +
  • +

    Releases starting with 0.4.0 onwards are published with SHA256 checksum + files for all release assets. These files are not yet validated by the + installer or updater however.

    +
  • +
  • +

    The install command can now install tools from custom indexes. #240

    +
  • +
  • +

    Virtualenvs on Unix are now created with a hack to pre-configure TCL and + TKinter. #233

    +
  • +
  • +

    Fix invalid version error when using rye init with custom toolchain. #234

    +
  • +
  • +

    Failed tool installations now properly clean up. #225

    +
  • +
  • +

    Correctly swap the rye executable on windows when performing an update + to a git version via self update.

    +
  • +
+

0.3.0

+

Released on 2023-05-27

+
    +
  • +

    Support retrieving username and repository-url from credentials if not + provided for the publish command. #217

    +
  • +
  • +

    The installer now validates the availability of shared libraries + on Linux with ldd and emits an error with additional information + if necessary shared libraries are missing. #220

    +
  • +
  • +

    It's now possible to configure http and https proxies. #215

    +
  • +
  • +

    If a package is not found because it only has matching pre-releases, + a warning is now printed to tell the user to pass --pre. #218

    +
  • +
  • +

    Add --username parameter for rye publish. #211

    +
  • +
  • +

    The shims are now more resilient. Previously a pyproject.toml file + caused in all cases a virtualenv to be created. Now this will only + happen when the rye.tool.managed flag is set to true. The old + behavior can be forced via the global config. #212

    +
  • +
+

0.2.0

+

Released on 2023-05-23

+
    +
  • +

    Resolved a bug where on Windows hitting the shift key (or some other keys) + in confirm prompts would cause an error.

    +
  • +
  • +

    The installer on Windows now warns if symlinks are not enabled and directs + the user to enable developer mode. The --version output now also + shows if symlinks are available. #205

    +
  • +
  • +

    Support auto fix requires-python when there is a conflict. #160

    +
  • +
  • +

    Added support for custom indexes. #199

    +
  • +
  • +

    rye add no longer complains when a local version information is + in the version. #199

    +
  • +
+

0.1.2

+

Released on 2023-05-22

+
    +
  • +

    Fixed dev-dependencies not being installed when using workspace. #170

    +
  • +
  • +

    init no longer creates invalid flit config. #195

    +
  • +
  • +

    Support direct references when adding a package. #158

    +
  • +
  • +

    Fixed a bug with uninstall on Unix platforms. #197

    +
  • +
+

0.1.1

+

Released on 2023-05-18

+
    +
  • +

    The installer on windows will now ask for a key to be pressed so it does + not close the window without information. #183

    +
  • +
  • +

    Fixed an issue on macOS where the installer would die with "os error 24" + when directly piped to bash. #184

    +
  • +
+

0.1.0

+

Released on 2023-05-17

+
    +
  • +

    Rye now comes with binary releases for some platforms.

    +
  • +
  • +

    A new self uninstall command was added to uninstall rye and the new + self update command updates to the latest release version.

    +
  • +
  • +

    Rye now includes a publish command for publishing Python packages to a + package repository. #86

    +
  • +
  • +

    Script declarations in pyproject.toml now permit chaining and custom + environment variables. #153

    +
  • +
  • +

    Added tools install and tools uninstall as aliases for install and + uninstall and added tools list to show all installed tools.

    +
  • +
  • +

    Rye is now capable of downloading a selected set of PyPy releases. To do + so use rye pin pypy@3.9.16 or any other supported PyPy release.

    +
  • +
  • +

    Custom cpython toolchains are now registered just as cpython rather + than custom-cpython.

    +
  • +
  • +

    Rye now supports Python down to 3.7.

    +
  • +
  • +

    Rye's self command now includes a completion subcommand to generate + a completion script for your shell.

    +
  • +
  • +

    The downloaded Python distributions are now validated against the + SHA-256 hashes.

    +
  • +
  • +

    Rye now builds on windows. This is even more experimental though + than support for Linux and macOS.

    +
  • +
  • +

    Added --features and --all-features for lock and sync.

    +
  • +
  • +

    Rye will now look at the RYE_HOME to determine the location of the + .rye folder. If it's not set, $HOME/.rye is used as before.

    +
  • +
  • +

    Rye now has a most consistent handling for virtualenv versions. If + .python-version is provided, that version is used. Otherwise if + requires-python is set in the pyproject.toml, that version is used + instead. When a new project is created the .python-version file is + written and the current latest cpython version is picked.

    +
  • +
  • +

    It's now possible to explicitly set the name of the project when + initializing a new one.

    +
  • +
  • +

    Rye's init command now attempts to initialize projects with git and + will automatically create a src/project_name/__init__.py file.

    +
  • +
  • +

    Rye can now also generate a license text when initializing projects.

    +
  • +
  • +

    Rye now supports negative (exclusion) dependencies. These can be used to + prevent a dependency from installing, even if something else in the graph + depends on it. Use rye add --exclude package-name to add such a dependency.

    +
  • +
  • +

    sync now accepts --no-lock to prevent updating the lock file.

    +
  • +
  • +

    Rye's add command now accepts a --pre parameter to include pre-release.

    +
  • +
  • +

    Rye's pin command now updates the pyproject.toml requires-python.

    +
  • +
  • +

    Rye's install command now accepts a --include-dep parameter to include + scripts from one or more given dependencies.

    +
  • +
  • +

    Rye now honors requires-python in the add command. This means the the + initial resolution will not pick a version higher than what's supported by + the lower boundary.

    +
  • +
  • +

    When installing packages as global tools, a warning is now emitted if there + were no scripts in the package. Additionally installing packages from local + paths and zip files is now supported.

    +
  • +
  • +

    A rye self update command was added to compile and install the latest + version via cargo.

    +
  • +
  • +

    Added more convenient ways to install from git/urls by supplying a --git + or --url parameter. This will behind the scenes format a PEP 508 requirement + string.

    +
  • +
  • +

    Added a shell command which will spawn a shell with the virtualenv activated.

    +
  • +
  • +

    Added a make-req command to conveniently format out PEP 508 requirement + strings from parts.

    +
  • +
  • +

    The internal virtualenv used to manage pip-tools and other libraries now + automatically updates when necessary.

    +
  • +
  • +

    rye toolchain register can now be used to register a local python installation + as toolchain with rye.

    +
  • +
  • +

    rye build was added to allow building sdist and bdist_wheel distributions.

    +
  • +
  • +

    Rye now correctly handles whitespace in folder names.

    +
  • +
+ + + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/community/index.html b/community/index.html new file mode 100644 index 0000000000..e9b26c37df --- /dev/null +++ b/community/index.html @@ -0,0 +1,1522 @@ + + + + + + + + + + + + + + + + + + + + + + + + Community - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + + + + + + + + +
+
+ + + + + + + + + + + + +

Community

+

Rye is a new project and feedback is greatly appreciated. Lots of it. Because +of this there are various different ways in which you can engage with either +the developer or other members of the community:

+ +

You can also reach out via Twitter or +Bluesky.

+

Badges

+

Want to show that you are using Rye? Why not throw a badge into your project's README.md:

+
[![Rye](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/rye/main/artwork/badge.json)](https://rye-up.com)
+
+

... or README.rst:

+
.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/rye/main/artwork/badge.json
+    :target: https://rye-up.com
+    :alt: Rye
+
+

... or, as HTML:

+
<a href="https://rye-up.com"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/rye/main/artwork/badge.json" alt="Rye" style="max-width:100%;"></a>
+
+

Rye

+ + + + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/get b/get new file mode 100755 index 0000000000..774929c09d --- /dev/null +++ b/get @@ -0,0 +1,82 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Wrap everything in a function so that a truncated script +# does not have the chance to cause issues. +__wrap__() { + +# allow overriding the version +VERSION=${RYE_VERSION:-latest} +# allow overriding the install option +INSTALL_OPTION=${RYE_INSTALL_OPTION:-""} + +REPO=astral-sh/rye +PLATFORM=`uname -s` +ARCH=`uname -m` + +if [[ $PLATFORM == "Darwin" ]]; then + PLATFORM="macos" +elif [[ $PLATFORM == "Linux" ]]; then + PLATFORM="linux" +fi + +if [[ $ARCH == armv8* ]] || [[ $ARCH == arm64* ]] || [[ $ARCH == aarch64* ]]; then + ARCH="aarch64" +elif [[ $ARCH == i686* ]]; then + ARCH="x86" +fi + +BINARY="rye-${ARCH}-${PLATFORM}" + +# Oddly enough GitHub has different URLs for latest vs specific version +if [[ $VERSION == "latest" ]]; then + DOWNLOAD_URL=https://github.com/${REPO}/releases/latest/download/${BINARY}.gz +else + DOWNLOAD_URL=https://github.com/${REPO}/releases/download/${VERSION}/${BINARY}.gz +fi + +echo "This script will automatically download and install rye (${VERSION}) for you." +if [ "x$(id -u)" == "x0" ]; then + echo "warning: this script is running as root. This is dangerous and unnecessary!" +fi + +if ! hash curl 2> /dev/null; then + echo "error: you do not have 'curl' installed which is required for this script." + exit 1 +fi + +if ! hash gunzip 2> /dev/null; then + echo "error: you do not have 'gunzip' installed which is required for this script." + exit 1 +fi + +TEMP_FILE=`mktemp "${TMPDIR:-/tmp}/.ryeinstall.XXXXXXXX"` +TEMP_FILE_GZ="${TEMP_FILE}.gz" + +cleanup() { + rm -f "$TEMP_FILE" + rm -f "$TEMP_FILE_GZ" +} + +trap cleanup EXIT +HTTP_CODE=$(curl -SL --progress-bar "$DOWNLOAD_URL" --output "$TEMP_FILE_GZ" --write-out "%{http_code}") +if [[ ${HTTP_CODE} -lt 200 || ${HTTP_CODE} -gt 299 ]]; then + echo "error: platform ${PLATFORM} (${ARCH}) is unsupported." + exit 1 +fi + +rm -f "$TEMP_FILE" +gunzip "$TEMP_FILE_GZ" +chmod +x "$TEMP_FILE" + +# Detect when the file cannot be executed due to NOEXEC /tmp. Taken from rustup +# https://github.com/rust-lang/rustup/blob/87fa15d13e3778733d5d66058e5de4309c27317b/rustup-init.sh#L158-L159 +if [ ! -x "$TEMP_FILE" ]; then + printf '%s\n' "Cannot execute $TEMP_FILE (likely because of mounting /tmp as noexec)." 1>&2 + printf '%s\n' "Please copy the file to a location where you can execute binaries and run it manually." 1>&2 + exit 1 +fi + +"$TEMP_FILE" self install $INSTALL_OPTION + +}; __wrap__ diff --git a/guide/basics/index.html b/guide/basics/index.html new file mode 100644 index 0000000000..526fa687ca --- /dev/null +++ b/guide/basics/index.html @@ -0,0 +1,1655 @@ + + + + + + + + + + + + + + + + + + + + + + + + Basics - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Basics

+

To use Rye you need to have a pyproject.toml based Python project. For this guide you can +create one with rye init which will create a new folder with a new project inside:

+
rye init my-project
+cd my-project
+
+

The following structure will be created:

+
.
+├── .git
+├── .gitignore
+├── .python-version
+├── README.md
+├── pyproject.toml
+└── src
+    └── my_project
+        └── __init__.py
+
+
+

Good to Know

+

The init command accepts a lot of options to customize what it generates. Run +rye init --help to see all the options available in the version you have installed.

+
+

A pyproject.toml is used to store metadata about your project as well as some Rye +configuration. Most of Rye's commands will require a pyproject.toml to work. Note +that Rye today does not support setup.py based projects. Note that when Rye initializes +a project it also writes a .python-version file. This file contains the version number +of the Python version that should be used for this project. It can be changed by +running rye pin. For instance to tell Rye to use Python 3.10:

+
$ rye pin 3.10
+
+

First Sync

+

Once that is done, you can use rye sync to get the first synchronization. After that, +Rye will have created a virtualenv in .venv and written lockfiles into requirements.lock +and requirements-dev.lock.

+
rye sync
+
+

The virtualenv that Rye manages is placed in .venv next to your pyproject.toml. +The first time you run this you will notice that Rye automatically downloaded and +installed a compatible CPython interpreter for you. If you have already another +Python installation on your system it will not be used! For more information about +this behavior read about toolchains.

+

You can activate and work with it as normal with one notable exception: the Python +installation in it does not contain pip. If you have correctly installed Rye +with the shims enabled, after the sync you can run python and you will automatically +be operating in that virtualenv, even if it's not enabled. You can validate this +by printing out sys.prefix:

+
python -c "import sys; print(sys.prefix)"
+
+

It will print out the full path to the managed virtualenv.

+

Adding Dependencies

+

Use the add command to add dependencies to your project.

+
rye add "flask>=2.0"
+
+

Note that after add you need to run sync again to actually install it. If you +want to add packages from custom indexes, you have to configure the source +first.

+

Listing Dependencies

+

You can invoke rye list to get a dump of all installed dependencies of your project. +Note that this only lists dependencies that are actually installed, so make sure to sync first.

+
rye list
+
+

Remove a Dependency

+

Use the remove command to remove a dependency from the project again.

+
rye remove flask
+
+

Working with the Project

+

To run executables in the context of the virtualenv you can use the run command. For +instance if you want to use black you can add and run it like this:

+
rye add black
+rye sync
+rye run black
+
+

If you want to have the commands available directly you will need to activate the +virtualenv like you do normally. To activate the virtualenv, use the standard methods:

+
+
+
+
. .venv/bin/activate
+
+
+
+
.venv\Scripts\activate
+
+
+
+
+

To deactivate it again run deactivate:

+
deactivate
+
+

Inspecting the Project

+

The rye show command can print out information about the project's state. By +just running rye show you can see which Python version is used, where the +virtualenv is located and more.

+
rye show
+
+

Executable projects

+

To generate a project that is aimed to provide an executable +script, use rye init --script:

+
rye init --script my-project
+cd my-project
+
+

The following structure will be created:

+
.
+├── .git
+├── .gitignore
+├── .python-version
+├── README.md
+├── pyproject.toml
+└── src
+    └── my_project
+        └── __init__.py
+        └── __main__.py
+
+

The pyproject.toml will be generated with a +[project.scripts] section named hello +that points to the main() function of __init__.py. After you +synchronized your changes, you can run the script with rye run hello.

+
rye sync
+rye run hello
+
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/add/index.html b/guide/commands/add/index.html new file mode 100644 index 0000000000..6cae306836 --- /dev/null +++ b/guide/commands/add/index.html @@ -0,0 +1,1599 @@ + + + + + + + + + + + + + + + + + + + + + + + + add - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

add

+

Adds a Python package to this project. The command takes a PEP 508 requirement string +but provides additional helper arguments to make this process more user friendly. For +instance instead of passing git references within the requiement string, the --git +parameter can be used.

+

If auto sync is disabled, after a dependency is added it's not automatically +installed. To do that, you need to invoke the sync command or pass +--sync. To remove a dependency again use the remove command.

+
+

new in 0.26.0

+

Added support for auto-sync and the --sync / --no-sync flags.

+
+

Example

+

Add the latest version of a dependency that is compatible with the configured Python version:

+
$ rye add flask
+Added flask>=3.0.1 as regular dependency
+
+

Add a dependency but add an optional extra feature:

+
$ rye add flask --features dotenv
+Added flask[dotenv]>=3.0.1 as regular dependency
+
+

Add a git dependency:

+
$ rye add flask --git https://github.com/pallets/flask
+Added flask @ git+https://github.com/pallets/flask as regular dependency
+
+

Add a local dependency:

+
$ rye add packagename --path path/to/packagename
+Added packagename @ file:///path/to/packagename as regular dependency
+
+

Arguments

+
    +
  • <REQUIREMENTS>...: The package to add as PEP 508 requirement string. e.g. 'flask==2.2.3'
  • +
+

Options

+
    +
  • +

    --git <GIT>: Install the given package from this git repository

    +
  • +
  • +

    --url <URL>: Install the given package from this URL

    +
  • +
  • +

    --path <PATH>: Install the given package from this local path

    +
  • +
  • +

    --absolute: Force non interpolated absolute paths

    +
  • +
  • +

    --tag <TAG>: Install a specific tag

    +
  • +
  • +

    --rev <REV>: Update to a specific git rev

    +
  • +
  • +

    --branch <BRANCH>: Update to a specific git branch

    +
  • +
  • +

    --features <FEATURES>: Adds a dependency with a specific feature

    +
  • +
  • +

    --dev: Add this as dev dependency

    +
  • +
  • +

    --excluded: Add this as an excluded dependency that will not be installed even if it's a sub dependency

    +
  • +
  • +

    --optional <OPTIONAL>: Add this to an optional dependency group

    +
  • +
  • +

    --pre: Include pre-releases when finding a package version

    +
  • +
  • +

    --pin <PIN>: Overrides the pin operator [possible values: equal, tilde-equal``,greater-than-equal``]

    +
  • +
  • +

    --sync: Runs sync automatically even if auto-sync is disabled.

    +
  • +
  • +

    --no-sync: Does not run sync automatically even if auto-sync is enabled.

    +
  • +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/build/index.html b/guide/commands/build/index.html new file mode 100644 index 0000000000..2a118180a5 --- /dev/null +++ b/guide/commands/build/index.html @@ -0,0 +1,1567 @@ + + + + + + + + + + + + + + + + + + + + + + + + build - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

build

+

Builds a package for distribution.

+

Under normal circumstances Rye automatically builds packages for +local development. However if you want to publish packages you need +to first build them into source distributions (sdist) and +binary/portable distributions (wheel).

+

For more information see Building and Publishing.

+

Example

+

This builds wheels and source distributions at once:

+
$ rye build
+building my-project
+* Creating virtualenv isolated environment...
+* Installing packages in isolated environment... (hatchling)
+* Getting build dependencies for sdist...
+* Building sdist...
+* Building wheel from sdist
+* Creating virtualenv isolated environment...
+* Installing packages in isolated environment... (hatchling)
+* Getting build dependencies for wheel...
+* Building wheel...
+Successfully built my_project-0.1.0.tar.gz and my_project-0.1.0-py3-none-any.whl
+
+

By default you will find the artifacts in the dist folder.

+

Arguments

+

no arguments

+

Options

+
    +
  • +

    --sdist: Build an sdist

    +
  • +
  • +

    --wheel: Build a wheel

    +
  • +
  • +

    -a, --all: Build all packages

    +
  • +
  • +

    -p, --package <PACKAGE>: Build a specific package

    +
  • +
  • +

    -o, --out <OUT>: An output directory (defaults to workspace/dist)

    +
  • +
  • +

    --pyproject <PYPROJECT_TOML>: Use this `pyproject.toml`` file

    +
  • +
  • +

    -c, --clean: Clean the output directory first

    +
  • +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/config/index.html b/guide/commands/config/index.html new file mode 100644 index 0000000000..e6dc3adbaa --- /dev/null +++ b/guide/commands/config/index.html @@ -0,0 +1,1556 @@ + + + + + + + + + + + + + + + + + + + + + + + + config - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

config

+

Reads or modifies the global config.toml file.

+

The config file can be read via --get and it can be set with one of the set options (--set, --set-int, +--set-bool, or --unset). Each of the set operations takes a key=value pair. All of these can be supplied +multiple times.

+

Example

+

This command turns on global shims:

+
rye config --set-bool behavior.global-python=true
+
+

Reads the currently set config value for global Python shims:

+
$ rye config --get behavior.global-python
+true
+
+

Show the path to the config:

+
$ rye config --show-path
+/Users/username/.rye/config.toml
+
+

Arguments

+

no arguments

+

Options

+
    +
  • +

    --get <GET>: Reads a config key

    +
  • +
  • +

    --set <SET>: Sets a config key to a string

    +
  • +
  • +

    --set-int <SET_INT>: Sets a config key to an integer

    +
  • +
  • +

    --set-bool <SET_BOOL>: Sets a config key to a bool

    +
  • +
  • +

    --unset <UNSET>: Remove a config key

    +
  • +
  • +

    --show-path: Print the path to the config

    +
  • +
  • +

    --format <FORMAT>: Request parseable output format rather than lines

    +

    [possible values: json]

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/fetch/index.html b/guide/commands/fetch/index.html new file mode 100644 index 0000000000..32baa49926 --- /dev/null +++ b/guide/commands/fetch/index.html @@ -0,0 +1,1549 @@ + + + + + + + + + + + + + + + + + + + + + + + + fetch - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

fetch

+

Fetches a Python interpreter for the local machine. This command is +available under the aliases rye fetch and rye toolchain fetch.

+

Example

+

Fetch a specific version of Python:

+
$ rye fetch 3.8.13
+Downloading cpython@3.8.13
+Checking checksum
+Unpacking
+Downloaded cpython@3.8.13
+
+

To fetch the pinned version of Python you can leave out the argument:

+
$ rye fetch
+Downloading cpython@3.8.17
+Checking checksum
+Unpacking
+Downloaded cpython@3.8.17
+
+

Arguments

+
    +
  • +

    [VERSION]: The version of Python to fetch.

    +

    If no version is provided, the requested version will be fetched.

    +
  • +
+

Options

+
    +
  • +

    -f, --force: Fetch the Python toolchain even if it is already installed.

    +
  • +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/fmt/index.html b/guide/commands/fmt/index.html new file mode 100644 index 0000000000..6c07e4a0dd --- /dev/null +++ b/guide/commands/fmt/index.html @@ -0,0 +1,1578 @@ + + + + + + + + + + + + + + + + + + + + + + + + fmt - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

fmt

+
+

new in 0.20.0

+
+

Run the code formatter on the project. This command is aliased to format.

+

For more information about how to configure Ruff, have a look at the +Ruff Configuration Documentation.

+

Example

+

To format the code and write back to the files:

+
$ rye fmt
+1 file reformatted, 231 files left unchanged
+
+

To just check if the code needs formatting:

+
$ rye fmt --check
+Would reformat: src/my_project/utils.py
+1 file would be reformatted, 231 files already formatted
+
+

To pass extra arguments to the underlying ruff formatter use --:

+
$ rye fmt -- --diff
+--- src/my_project/utils.py
++++ src/my_project/utils.py
+@@ -2,5 +2,4 @@
+
+
+ def foo():
+-
+     pass
+
+1 file would be reformatted, 231 files already formatted
+
+

Format a specific file:

+
rye fmt src/foo.py
+
+

Arguments

+
    +
  • +

    [PATHS]... List of files or directories to lint. If not supplied all files are formatted.

    +
  • +
  • +

    [EXTRA_ARGS]... Extra arguments to the formatter.

    +

    These arguments are forwarded directly to the underlying formatter (currently +always ruff). Note that extra arguments must be separated from other arguments +with the -- marker.

    +
  • +
+

Options

+
    +
  • +

    -a, --all: Format all packages in the workspace

    +
  • +
  • +

    -p, --package <PACKAGE>: Format a specific package

    +
  • +
  • +

    --pyproject <PYPROJECT_TOML>: Use this pyproject.toml file

    +
  • +
  • +

    --check: Run format in check mode

    +
  • +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/index.html b/guide/commands/index.html new file mode 100644 index 0000000000..e244912625 --- /dev/null +++ b/guide/commands/index.html @@ -0,0 +1,1489 @@ + + + + + + + + + + + + + + + + + + + + + + + + Overview - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Commands

+

This is a list of all the commands that rye provides:

+
    +
  • add: Adds a Python package to this project
  • +
  • build: Builds a package for distribution
  • +
  • config: Reads or updates the Rye configuration
  • +
  • fetch: Fetches a Python interpreter for the local machine (alias)
  • +
  • fmt: Run the code formatter on the project
  • +
  • init: Initializes a new project
  • +
  • install: Installs a global tool (alias)
  • +
  • lock: Updates the lockfiles without installing dependencies
  • +
  • lint: Run the linter on the project
  • +
  • make-req: Builds and prints a PEP 508 requirement string from parts
  • +
  • pin: Pins a Python version to the project
  • +
  • publish: Publish packages to a package repository
  • +
  • remove: Remove a dependency from this project
  • +
  • run: Runs a command installed into this package
  • +
  • show: Prints the current state of the project
  • +
  • sync: Updates the virtualenv based on the pyproject.toml
  • +
  • toolchain: Helper utility to manage Python toolchains
  • +
  • tools: Helper utility to manage global tools.
  • +
  • self: Rye self management
  • +
  • uninstall: Uninstalls a global tool (alias)
  • +
  • version: Get or set project version
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/init/index.html b/guide/commands/init/index.html new file mode 100644 index 0000000000..f7e6d53986 --- /dev/null +++ b/guide/commands/init/index.html @@ -0,0 +1,1574 @@ + + + + + + + + + + + + + + + + + + + + + + + + init - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

init

+

This command initializes a new or existing Python project with Rye. Running it in +a folder with an already existing Python project will attempt to convert it over +and bootstrap Rye right there. Otherwise it can be used to create a completely new +project from scratch.

+

For more information see the Basics Guide.

+

Example

+
$ rye init
+success: Initialized project in /Users/john/Development/my-project.
+  Run `rye sync` to get started
+
+

Arguments

+
    +
  • [PATH]: Where to place the project (defaults to current path)
  • +
+

Options

+
    +
  • +

    --min-py <MIN_PY>: Minimal Python version supported by this project

    +
  • +
  • +

    -p, --py <PY>: Python version to use for the virtualenv

    +
  • +
  • +

    --no-readme: Do not create a readme

    +
  • +
  • +

    --no-pin: Do not create .python-version file (requires-python will be used)

    +
  • +
  • +

    --build-system <BUILD_SYSTEM>: Which build system should be used(defaults to hatchling)?

    +

    [possible values: hatchling, setuptools, flit, pdm, maturin]

    +
  • +
  • +

    --license <LICENSE>: Which license should be used? SPDX identifier

    +
  • +
  • +

    --name <NAME>: The name of the package

    +
  • +
  • +

    --private: Set "Private :: Do Not Upload" classifier, used for private projects

    +
  • +
  • +

    --no-import: Don't import from setup.cfg, setup.py, or requirements files

    +
  • +
  • +

    --virtual: Initialize this as a virtual package.

    +

    A virtual package can have dependencies but is itself not installed as a Python package. It also cannot be published.

    +
  • +
  • +

    -r, --requirements <REQUIREMENTS_FILE>: Requirements files to initialize pyproject.toml with

    +
  • +
  • +

    --dev-requirements <DEV_REQUIREMENTS_FILE>: Development requirements files to initialize pyproject.toml with

    +
  • +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/install/index.html b/guide/commands/install/index.html new file mode 100644 index 0000000000..79cfb25d69 --- /dev/null +++ b/guide/commands/install/index.html @@ -0,0 +1,1594 @@ + + + + + + + + + + + + + + + + + + + + + + + + install - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

install

+

Installs a package as global tool. This command has two names +to rye tools install and rye install.

+

This can be used to install useful Python scripts globally into it's own +separated virtualenv. For instance if you want to use the black formatter +you can install it once.

+

Normally only scripts installed by the top level dependency are installed. In +some cases you might also want to install commands from sub-dependencies. In +that case pass those dependencies with --include-dep.

+

For more information see Tools.

+

Example

+
$ rye tools install pycowsay
+Looking in indexes: https://pypi.org/simple/
+Collecting pycowsay
+  Downloading pycowsay-0.0.0.2-py3-none-any.whl.metadata (965 bytes)
+Downloading pycowsay-0.0.0.2-py3-none-any.whl (4.0 kB)
+Installing collected packages: pycowsay
+Successfully installed pycowsay-0.0.0.2
+
+Installed scripts:
+  - pycowsay
+
+$ pycowsay "Great Stuff"
+
+  -----------
+< Great Stuff >
+  -----------
+   \   ^__^
+    \  (oo)\_______
+       (__)\       )\/\
+           ||----w |
+           ||     ||
+
+

Arguments

+
    +
  • <REQUIREMENT>...: The package to install as PEP 508 requirement string.
  • +
+

Options

+
    +
  • +

    --git <GIT>: Install the given package from this git repository

    +
  • +
  • +

    --url <URL>: Install the given package from this URL

    +
  • +
  • +

    --path <PATH>: Install the given package from this local path

    +
  • +
  • +

    --absolute: Force non interpolated absolute paths

    +
  • +
  • +

    --tag <TAG>: Install a specific tag

    +
  • +
  • +

    --rev <REV>: Update to a specific git rev

    +
  • +
  • +

    --branch <BRANCH>: Update to a specific git branch

    +
  • +
  • +

    --features <FEATURES>: Adds a dependency with a specific feature

    +
  • +
  • +

    --include-dep <INCLUDE_DEP>: Include scripts from a given dependency

    +
  • +
  • +

    --extra-requirement <EXTRA_REQUIREMENT>: Additional dependencies to install that are not declared by the main package

    +
  • +
  • +

    -p, --python <PYTHON>: Optionally the Python version to use

    +
  • +
  • +

    -f, --force: Force install the package even if it's already there

    +
  • +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/lint/index.html b/guide/commands/lint/index.html new file mode 100644 index 0000000000..bd077829dc --- /dev/null +++ b/guide/commands/lint/index.html @@ -0,0 +1,1570 @@ + + + + + + + + + + + + + + + + + + + + + + + + lint - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

lint

+
+

new in 0.20.0

+
+

Run the linter on the project. This command is aliased to check. At the moment +this always runs ruff in lint mode.

+

For more information about how to configure Ruff, have a look at the +Ruff Configuration Documentation.

+

Example

+

Run the linter:

+
$ rye lint
+src/myproject/sdk.py:1:8: F401 [*] `sys` imported but unused
+Found 1 error.
+[*] 1 fixable with the `--fix` option.
+
+

For issues that can be auto fixed pass --fix:

+
$ rye lint --fix
+Found 1 error (1 fixed, 0 remaining).
+
+

To pass extra arguments:

+
$ rye lint -- --watch
+
+

Lint a specific file:

+
rye lint src/foo.py
+
+

Arguments

+
    +
  • +

    [PATHS]... List of files or directories to lint. If not supplied all files are linted.

    +
  • +
  • +

    [EXTRA_ARGS]... Extra arguments to the linter.

    +

    These arguments are forwarded directly to the underlying linter (currently +always ruff). Note that extra arguments must be separated from other arguments +with the -- marker.

    +
  • +
+

Options

+
    +
  • +

    -a, --all: Lint all packages in the workspace

    +
  • +
  • +

    -p, --package <PACKAGE>: Format a specific package

    +
  • +
  • +

    --pyproject <PYPROJECT_TOML>: Use this pyproject.toml file

    +
  • +
  • +

    --fix: Automatically fix fixable issues

    +
  • +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/list/index.html b/guide/commands/list/index.html new file mode 100644 index 0000000000..851be6a44b --- /dev/null +++ b/guide/commands/list/index.html @@ -0,0 +1,1435 @@ + + + + + + + + + + + + + + + + + + + + `list` - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

list

+
+

new in 0.24.0

+
+

Prints a list of installed dependencies.

+

Example

+
$ rye list
+asgiref==3.7.2
+blinker==1.7.0
+click==8.1.7
+Flask @ git+https://github.com/pallets/flask@4df377cfbfc1d15e962a61c18920b22aebc9aa41
+itsdangerous==2.1.2
+Jinja2==3.1.3
+MarkupSafe==2.1.4
+Werkzeug==3.0.1
+
+

Arguments

+

no arguments

+

Options

+
    +
  • +

    --pyproject: Use this pyproject.toml file

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/lock/index.html b/guide/commands/lock/index.html new file mode 100644 index 0000000000..e9d1ded4c1 --- /dev/null +++ b/guide/commands/lock/index.html @@ -0,0 +1,1554 @@ + + + + + + + + + + + + + + + + + + + + + + + + lock - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

lock

+

Updates the lockfiles without installing dependencies. Usually one would use +the sync command instead which both locks and installs dependencies.

+

For more information see Synching and Locking.

+

Example

+
$ rye lock
+Generating production lockfile: /Users/username/my-project/requirements.lock
+Generating dev lockfile: /Users/username/my-project/requirements-dev.lock
+Done!
+
+

Arguments

+

no arguments

+

Options

+
    +
  • +

    --update <UPDATE>: Update a specific package

    +
  • +
  • +

    --update-all: Update all packages to the latest

    +
  • +
  • +

    --pre: Update to pre-release versions

    +
  • +
  • +

    --features <FEATURES>: Extras/features to enable when locking the workspace

    +
  • +
  • +

    --all-features: Enables all features

    +
  • +
  • +

    --with-sources: Set to true to lock with sources in the lockfile

    +
  • +
  • +

    --pyproject <PYPROJECT_TOML>: Use this pyproject.toml file

    +
  • +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/make-req/index.html b/guide/commands/make-req/index.html new file mode 100644 index 0000000000..0e5936fcff --- /dev/null +++ b/guide/commands/make-req/index.html @@ -0,0 +1,1553 @@ + + + + + + + + + + + + + + + + + + + + + + + + make-req - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

make-req

+

Builds and prints a PEP 508 requirement string from parts. This is a utility command +that rarely needs to be used but can help creating requirements strings for pasting into +other tools. It takes the same arguments as add but rather than adding the +requirements into the requirements file it just spits out a formatted PEP 508 requirement +string on stdout.

+

Example

+
$ rye make-req flask --git https://github.com/pallets/flask --rev 4df377cfbf
+flask @ git+https://github.com/pallets/flask@4df377cfbf
+
+

Arguments

+
    +
  • [REQUIREMENTS]... The package to add as PEP 508 requirement string. e.g. 'flask==2.2.3'
  • +
+

Options

+
    +
  • +

    --git <GIT>: Install the given package from this git repository

    +
  • +
  • +

    --url <URL>: Install the given package from this URL

    +
  • +
  • +

    --path <PATH>: Install the given package from this local path

    +
  • +
  • +

    --absolute: Force non interpolated absolute paths

    +
  • +
  • +

    --tag <TAG>: Install a specific tag

    +
  • +
  • +

    --rev <REV>: Update to a specific git rev

    +
  • +
  • +

    --branch <BRANCH>: Update to a specific git branch

    +
  • +
  • +

    --features <FEATURES>: Adds a dependency with a specific feature

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/pin/index.html b/guide/commands/pin/index.html new file mode 100644 index 0000000000..a3563741df --- /dev/null +++ b/guide/commands/pin/index.html @@ -0,0 +1,1551 @@ + + + + + + + + + + + + + + + + + + + + + + + + pin - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

pin

+

Pins a Python version to this project.

+

This will update the .python-version to point to the provided version. +Additionally it will update requires-python in the pyproject.toml if it's +lower than the current version. This can be disabled by passing +--no-update-requires-python.

+

Which toolchain Rye prefers depends on the Rye version. From 0.22 onwards +the latest compatible installed toolchain is picked, and only if a non +existing one is found a download will be attempted. For older versions +Rye will always attempt to download the latest available if it's not +installed yet unless a precise pin is selected.

+

Example

+

Pin a specific version of Python:

+
$ rye pin 3.9
+pinned 3.9.18 in /Users/username/my-project
+
+

To issue a relaxed and not a specific pin use --relaxed:

+
$ rye pin 3.9 --relaxed
+pinned 3.9 in /Users/username/my-project
+
+

Arguments

+
    +
  • +

    <VERSION>: The version of Python to pin

    +

    This can be a short version (3.9) or a full one (cpython@3.9.18).

    +
  • +
+

Options

+
    +
  • +

    --relaxed: Issue a relaxed pin

    +
  • +
  • +

    --no-update-requires-python: Prevent updating requires-python in the pyproject.toml

    +
  • +
  • +

    --pyproject <PYPROJECT_TOML>: Use this pyproject.toml file

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/publish/index.html b/guide/commands/publish/index.html new file mode 100644 index 0000000000..8363ccf6d1 --- /dev/null +++ b/guide/commands/publish/index.html @@ -0,0 +1,1564 @@ + + + + + + + + + + + + + + + + + + + + + + + + publish - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

publish

+

Publish packages to a package repository. This publishes the packages which are +produced by the build command.

+

For more information see Building and Publishing.

+

Example

+

Build and publish:

+
$ rye build
+$ rye publish
+
+

Publish a specific artifact:

+
$ rye publish dist/example-0.1.0.tar.gz
+
+

Arguments

+
    +
  • [DIST]...: The distribution files to upload to the repository (defaults to <workspace-root>/dist/*)
  • +
+

Options

+
    +
  • +

    -r, --repository <REPOSITORY>: The repository to publish to [default: pypi]

    +
  • +
  • +

    --repository-url <REPOSITORY_URL>: The repository url to publish to

    +
  • +
  • +

    -u, --username <USERNAME>: The username to authenticate to the repository with

    +
  • +
  • +

    --token <TOKEN>: An access token used for the upload

    +
  • +
  • +

    --sign: Sign files to upload using GPG

    +
  • +
  • +

    -i, --identity <IDENTITY>: GPG identity used to sign files

    +
  • +
  • +

    --cert <CERT>: Path to alternate CA bundle

    +
  • +
  • +

    --skip-existing: Skip files already published (repository must support this feature)

    +
  • +
  • +

    -y, --yes: Skip prompts

    +
  • +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/remove/index.html b/guide/commands/remove/index.html new file mode 100644 index 0000000000..38111c314b --- /dev/null +++ b/guide/commands/remove/index.html @@ -0,0 +1,1551 @@ + + + + + + + + + + + + + + + + + + + + + + + + remove - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

remove

+

Removes a package from this project. This removes a package from the pyproject.toml +dependency list.

+

If auto sync is disabled, after a dependency is removed it's not automatically +uninstalled. To do that, you need to invoke the sync command or pass +--sync.

+
+

new in 0.26.0

+

Added support for auto-sync and the --sync / --no-sync flags.

+
+

Example

+
$ rye remove flask
+Removed flask>=3.0.1
+
+

Arguments

+
    +
  • <REQUIREMENTS>...: The packages to remove from the project
  • +
+

Options

+
    +
  • +

    --dev: Remove this from dev dependencies

    +
  • +
  • +

    --optional <OPTIONAL>: Remove this from the optional dependency group

    +
  • +
  • +

    --sync: Runs sync automatically even if auto-sync is disabled.

    +
  • +
  • +

    --no-sync: Does not run sync automatically even if auto-sync is enabled.

    +
  • +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/run/index.html b/guide/commands/run/index.html new file mode 100644 index 0000000000..e7d5bd82a0 --- /dev/null +++ b/guide/commands/run/index.html @@ -0,0 +1,1541 @@ + + + + + + + + + + + + + + + + + + + + + + + + run - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

run

+

Runs a command installed into this package. This either runs a script or application +made available in the virtualenv or a Rye specific script.

+

For more information see rye.tool.scripts.

+

Example

+

Run a tool from the virtualenv:

+
$ rye run flask
+
+

Invoke it without arguments to see all available scripts:

+
$ rye run
+flask
+hello
+python
+python3
+python3.9
+
+

Arguments

+
    +
  • [COMMAND]: The name of the command and the arguments to it.
  • +
+

Options

+
    +
  • +

    -l, --list: List all commands (implied without arguments)

    +
  • +
  • +

    --pyproject: Use this pyproject.toml file

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/self/completion/index.html b/guide/commands/self/completion/index.html new file mode 100644 index 0000000000..44d987335e --- /dev/null +++ b/guide/commands/self/completion/index.html @@ -0,0 +1,1529 @@ + + + + + + + + + + + + + + + + + + + + + + + + completion - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

completion

+

Generates a completion script for a shell

+

Example

+

Generate a completion script for zsh and load it:

+
$ eval (rye self completion -s zsh)
+
+

Arguments

+

no arguments

+

Options

+
    +
  • +

    -s, --shell <SHELL>: The shell to generate a completion script for (defaults to 'bash')

    +

    [possible values: bash, elvish, fish, powershell, zsh]

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/self/index.html b/guide/commands/self/index.html new file mode 100644 index 0000000000..57292e0a2c --- /dev/null +++ b/guide/commands/self/index.html @@ -0,0 +1,1479 @@ + + + + + + + + + + + + + + + + + + + + + + + + Overview - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

self

+

Command to manage Rye itself.

+
    +
  • +

    completion: Generates a completion script for Rye.

    +
  • +
  • +

    update: Performs an update of Rye.

    +
  • +
  • +

    uninstall: Uninstalls Rye again.

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/self/uninstall/index.html b/guide/commands/self/uninstall/index.html new file mode 100644 index 0000000000..a9f2ae4c11 --- /dev/null +++ b/guide/commands/self/uninstall/index.html @@ -0,0 +1,1531 @@ + + + + + + + + + + + + + + + + + + + + + + + + uninstall - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

uninstall

+

Uninstalls rye again. Note that this leaves a trace +.rye folder behind with an empty env file. You also +need to remove the sourcing of that script from your +.profile file.

+

Example

+

Uninstall rye without asking:

+
$ rye self uninstall --yes
+
+

Arguments

+

no arguments

+

Options

+
    +
  • +

    -y, --yes: Do not prompt and uninstall.

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/self/update/index.html b/guide/commands/self/update/index.html new file mode 100644 index 0000000000..ab345354ce --- /dev/null +++ b/guide/commands/self/update/index.html @@ -0,0 +1,1545 @@ + + + + + + + + + + + + + + + + + + + + + + + + update - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

update

+

Performs an update of rye.

+

This can install updates from the latest release binaries or trigger a manual +compilation of Rye if Rust is installed.

+

Example

+

Update to the latest version:

+
$ rye self update
+
+

Update (or downgrade) to a specific version:

+
$ rye self update --version 0.20
+
+

Compile a specific revision:

+
$ rye self update --rev 08910bc9b3b7c72a3d3ac694c4f3412259161477
+
+

Arguments

+

no arguments

+

Options

+
    +
  • +

    --version <VERSION>: Update to a specific version

    +
  • +
  • +

    --tag <TAG>: Update to a specific tag

    +
  • +
  • +

    --rev <REV>: Update to a specific git rev

    +
  • +
  • +

    --force: Force reinstallation

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/show/index.html b/guide/commands/show/index.html new file mode 100644 index 0000000000..06380f9211 --- /dev/null +++ b/guide/commands/show/index.html @@ -0,0 +1,1537 @@ + + + + + + + + + + + + + + + + + + + + + + + + show - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

show

+

Prints the current state of the project. This can print out information about the +virtualenv, the project or workspace as well as a list of installed dependencies.

+

Example

+

Print out the status of a project:

+
$ rye show
+project: my-project
+path: /Users/username/my-project
+venv: /Users/username/my-project/.venv
+target python: 3.8
+venv python: cpython@3.9.18
+virtual: false
+
+

Arguments

+

no arguments

+

Options

+
    +
  • +

    --installed-deps: Print the currently installed dependencies.

    +

    This option is being replaced with rye list

    +
  • +
  • +

    --pyproject: Use this pyproject.toml file

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/sync/index.html b/guide/commands/sync/index.html new file mode 100644 index 0000000000..ba8324405d --- /dev/null +++ b/guide/commands/sync/index.html @@ -0,0 +1,1572 @@ + + + + + + + + + + + + + + + + + + + + + + + + sync - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

sync

+

Updates the lockfiles and installs the dependencies into the virtualenv.

+

For more information see Synching and Locking.

+

Example

+

Sync the project:

+
$ rye sync
+Reusing already existing virtualenv
+Generating production lockfile: /Users/username/my-project/requirements.lock
+Generating dev lockfile: /Users/username/my-project/requirements-dev.lock
+Installing dependencies
+...
+
+

To sync without updating the lock file use --no-lock:

+
$ rye sync --no-lock
+
+

If you do not want dev dependencies to be installed use --no-dev:

+
$ rye sync --no-dev
+
+

To exit the sub shell run exit.

+

Arguments

+

no arguments

+

Options

+
    +
  • +

    -f, --force: Force the virtualenv to be re-created

    +
  • +
  • +

    --no-dev: Do not install dev dependencies

    +
  • +
  • +

    --no-lock: Do not update the lockfile.

    +
  • +
  • +

    --update <UPDATE>: Update a specific package

    +
  • +
  • +

    --update-all: Update all packages to the latest

    +
  • +
  • +

    --pre: Update to pre-release versions

    +
  • +
  • +

    --features <FEATURES>: Extras/features to enable when locking the workspace

    +
  • +
  • +

    --all-features: Enables all features

    +
  • +
  • +

    --with-sources: Set to true to lock with sources in the lockfile

    +
  • +
  • +

    --pyproject <PYPROJECT_TOML>: Use this pyproject.toml file

    +
  • +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/toolchain/fetch/index.html b/guide/commands/toolchain/fetch/index.html new file mode 100644 index 0000000000..1d2b1dd9c0 --- /dev/null +++ b/guide/commands/toolchain/fetch/index.html @@ -0,0 +1,1551 @@ + + + + + + + + + + + + + + + + + + + + + + + + fetch - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

fetch

+

Fetches a Python interpreter for the local machine. This command is +available under the aliases rye fetch and rye toolchain fetch.

+

Example

+

Fetch a specific version of Python:

+
$ rye fetch 3.8.13
+Downloading cpython@3.8.13
+Checking checksum
+Unpacking
+Downloaded cpython@3.8.13
+
+

To fetch the pinned version of Python you can leave out the argument:

+
$ rye fetch
+Downloading cpython@3.8.17
+Checking checksum
+Unpacking
+Downloaded cpython@3.8.17
+
+

Arguments

+
    +
  • +

    [VERSION]: The version of Python to fetch.

    +

    If no version is provided, the requested version will be fetched.

    +
  • +
+

Options

+
    +
  • +

    -f, --force: Fetch the Python toolchain even if it is already installed.

    +
  • +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/toolchain/index.html b/guide/commands/toolchain/index.html new file mode 100644 index 0000000000..7edcbb51de --- /dev/null +++ b/guide/commands/toolchain/index.html @@ -0,0 +1,1482 @@ + + + + + + + + + + + + + + + + + + + + + + + + Overview - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

toolchain

+

Helper utility to manage Python toolchains. The following subcommands exist:

+
    +
  • +

    fetch: fetches a toolchain

    +
  • +
  • +

    list: lists all registered toolchains

    +
  • +
  • +

    register: register a Python binary as custom toolchain

    +
  • +
  • +

    remove: removes or uninstalls a toolchain

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/toolchain/list/index.html b/guide/commands/toolchain/list/index.html new file mode 100644 index 0000000000..896d41bccb --- /dev/null +++ b/guide/commands/toolchain/list/index.html @@ -0,0 +1,1541 @@ + + + + + + + + + + + + + + + + + + + + + + + + list - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

list

+

List all registered toolchains. It can list the toolchains which are installed as +well as toolchains which can be downloaded if --include-downloadable is passed.

+

Example

+

List installed toolchains:

+
$ rye toolchain list
+cpython@3.12.1 (/Users/username/.rye/py/cpython@3.12.1/install/bin/python3)
+cpython@3.11.6 (/Users/username/.rye/py/cpython@3.11.6/install/bin/python3)
+
+

Lists downloadable toolchains:

+
$ rye toolchain list --include-downloadable
+cpython@3.12.1 (/Users/mitsuhiko/.rye/py/cpython@3.12.1/install/bin/python3)
+cpython-x86_64@3.12.1 (downloadable)
+cpython@3.11.7 (downloadable)
+...
+
+

Arguments

+

no arguments

+

Options

+
    +
  • +

    --include-downloadable: Also include non installed, but downloadable toolchains

    +
  • +
  • +

    --format <FORMAT>: Request parseable output format [possible values: json]

    +
  • +
  • +

    -h, --help: Print help

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/toolchain/register/index.html b/guide/commands/toolchain/register/index.html new file mode 100644 index 0000000000..bff4b7269f --- /dev/null +++ b/guide/commands/toolchain/register/index.html @@ -0,0 +1,1535 @@ + + + + + + + + + + + + + + + + + + + + + + + + register - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

register

+

Register a Python binary as custom toolchain.

+

Rye by default will automatically download Python releases from the internet. +However it's also possible to register already available local Python +installations. This allows you to use rye with self compiled Pythons.

+

The name of the toolchain is auto detected (eg: cpython, pypy etc.)

+

To unregister use the remove command.

+

Example

+
$ rye toolchain register /opt/homebrew/Cellar/python@3.10/3.10.6_1/bin/python3.10
+Registered /opt/homebrew/Cellar/python@3.10/3.10.6_1/bin/python3.10 as cpython@3.10.6
+
+

Arguments

+
    +
  • <PATH>: Path to the python binary that should be registered
  • +
+

Options

+
    +
  • +

    -n, --name <NAME>: Name of the toolchain. If not provided a name is auto detected.

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/toolchain/remove/index.html b/guide/commands/toolchain/remove/index.html new file mode 100644 index 0000000000..ced321a0ba --- /dev/null +++ b/guide/commands/toolchain/remove/index.html @@ -0,0 +1,1526 @@ + + + + + + + + + + + + + + + + + + + + + + + + remove - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

remove

+

Removes or uninstalls a toolchain.

+

Example

+
$ rye toolchain remove 3.9.5
+Removed installed toolchain cpython@3.9.5
+
+

Arguments

+
    +
  • <VERSION> The version of Python to remove.
  • +
+

Options

+
    +
  • -f, --force: Force removal even if the toolchain is in use
  • +
  • -h, --help: Print help (see a summary with '-h')
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/tools/index.html b/guide/commands/tools/index.html new file mode 100644 index 0000000000..286a53e794 --- /dev/null +++ b/guide/commands/tools/index.html @@ -0,0 +1,1479 @@ + + + + + + + + + + + + + + + + + + + + + + + + Overview - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

tools

+

Helper utility to manage global tool installations.

+
    +
  • +

    install: installs a tool globally.

    +
  • +
  • +

    uninstall: uninstalls a globally installed tool.

    +
  • +
  • +

    list: lists all globally installed tools.

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/tools/install/index.html b/guide/commands/tools/install/index.html new file mode 100644 index 0000000000..242b92ecd9 --- /dev/null +++ b/guide/commands/tools/install/index.html @@ -0,0 +1,1596 @@ + + + + + + + + + + + + + + + + + + + + + + + + install - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

install

+

Installs a package as global tool. This command has two names +to rye tools install and rye install.

+

This can be used to install useful Python scripts globally into it's own +separated virtualenv. For instance if you want to use the black formatter +you can install it once.

+

Normally only scripts installed by the top level dependency are installed. In +some cases you might also want to install commands from sub-dependencies. In +that case pass those dependencies with --include-dep.

+

For more information see Tools.

+

Example

+
$ rye tools install pycowsay
+Looking in indexes: https://pypi.org/simple/
+Collecting pycowsay
+  Downloading pycowsay-0.0.0.2-py3-none-any.whl.metadata (965 bytes)
+Downloading pycowsay-0.0.0.2-py3-none-any.whl (4.0 kB)
+Installing collected packages: pycowsay
+Successfully installed pycowsay-0.0.0.2
+
+Installed scripts:
+  - pycowsay
+
+$ pycowsay "Great Stuff"
+
+  -----------
+< Great Stuff >
+  -----------
+   \   ^__^
+    \  (oo)\_______
+       (__)\       )\/\
+           ||----w |
+           ||     ||
+
+

Arguments

+
    +
  • <REQUIREMENT>...: The package to install as PEP 508 requirement string.
  • +
+

Options

+
    +
  • +

    --git <GIT>: Install the given package from this git repository

    +
  • +
  • +

    --url <URL>: Install the given package from this URL

    +
  • +
  • +

    --path <PATH>: Install the given package from this local path

    +
  • +
  • +

    --absolute: Force non interpolated absolute paths

    +
  • +
  • +

    --tag <TAG>: Install a specific tag

    +
  • +
  • +

    --rev <REV>: Update to a specific git rev

    +
  • +
  • +

    --branch <BRANCH>: Update to a specific git branch

    +
  • +
  • +

    --features <FEATURES>: Adds a dependency with a specific feature

    +
  • +
  • +

    --include-dep <INCLUDE_DEP>: Include scripts from a given dependency

    +
  • +
  • +

    --extra-requirement <EXTRA_REQUIREMENT>: Additional dependencies to install that are not declared by the main package

    +
  • +
  • +

    -p, --python <PYTHON>: Optionally the Python version to use

    +
  • +
  • +

    -f, --force: Force install the package even if it's already there

    +
  • +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/tools/list/index.html b/guide/commands/tools/list/index.html new file mode 100644 index 0000000000..b915010fd0 --- /dev/null +++ b/guide/commands/tools/list/index.html @@ -0,0 +1,1543 @@ + + + + + + + + + + + + + + + + + + + + + + + + list - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

list

+

Lists all already installed global tools.

+

For more information see Tools.

+

Example

+

List installed tools:

+
$ rye tools list
+pycowsay
+
+

List installed tools with version:

+
$ rye tools list --include-version
+pycowsay 0.0.0.2 (cpython@3.12.1)
+
+

Arguments

+

no arguments

+

Options

+
    +
  • -s, --include-scripts: Show all the scripts installed by the tools
  • +
+
+

changed in 0.26.0

+

Renamed from -i, --include-scripts to -s, --include-scripts.

+
+
    +
  • -v, --include-version: Show the version of tools
  • +
+
+

changed in 0.26.0

+

Renamed from -v, --version-show to -v, --include-version.

+
+
    +
  • -h, --help: Print help
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/tools/uninstall/index.html b/guide/commands/tools/uninstall/index.html new file mode 100644 index 0000000000..c0efbd04d7 --- /dev/null +++ b/guide/commands/tools/uninstall/index.html @@ -0,0 +1,1535 @@ + + + + + + + + + + + + + + + + + + + + + + + + uninstall - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

uninstall

+

Uninstalls an already installed global tool. This command has two names +to rye tools uninstall and rye uninstall.

+

For more information see Tools.

+

Example

+
$ rye tools uninstall pycowsay
+Uninstalled pycowsay
+
+

Arguments

+
    +
  • <NAME>: The package to uninstall.
  • +
+

Options

+
    +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/uninstall/index.html b/guide/commands/uninstall/index.html new file mode 100644 index 0000000000..2c54ee997a --- /dev/null +++ b/guide/commands/uninstall/index.html @@ -0,0 +1,1533 @@ + + + + + + + + + + + + + + + + + + + + + + + + uninstall - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

uninstall

+

Uninstalls an already installed global tool. This command has two names +to rye tools uninstall and rye uninstall.

+

For more information see Tools.

+

Example

+
$ rye tools uninstall pycowsay
+Uninstalled pycowsay
+
+

Arguments

+
    +
  • <NAME>: The package to uninstall.
  • +
+

Options

+
    +
  • +

    -v, --verbose: Enables verbose diagnostics

    +
  • +
  • +

    -q, --quiet: Turns off all output

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/commands/version/index.html b/guide/commands/version/index.html new file mode 100644 index 0000000000..f5be0a13cd --- /dev/null +++ b/guide/commands/version/index.html @@ -0,0 +1,1538 @@ + + + + + + + + + + + + + + + + + + + + + + + + version - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

version

+

Get or set project version. Note that this does not refer to the version of Rye +itself but the version that is set in the pyproject.toml file.

+

Example

+

Get the current version:

+
$ rye version
+0.1.0
+
+

Bump the version by minor:

+
$ rye version -b minor
+version bumped to 0.2.0
+
+

Set to a specific version:

+
$ rye version 1.0.0
+version set to 1.0.0
+
+

Arguments

+
    +
  • [VERSION]: the version to set
  • +
+

Options

+
    +
  • +

    -b, --bump <BUMP>: automatically bump the version in a specific way (major, minor or patch)

    +
  • +
  • +

    -h, --help: Print help (see a summary with '-h')

    +
  • +
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/config/index.html b/guide/config/index.html new file mode 100644 index 0000000000..bc29bf992d --- /dev/null +++ b/guide/config/index.html @@ -0,0 +1,1654 @@ + + + + + + + + + + + + + + + + + + + + + + + + Configuration - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Configuration

+

Most of Rye's configuration is contained within the pyproject.toml file. There is however +also a bit of global configuration to influence how it works.

+

Changing Home Folder

+

By default Rye places all it's configuration in ~/.rye on Unix and %USERPROFILE%\.rye on +Windows. This behavior can be changed via the RYE_HOME environment variable. This is useful +if you do not like the default location of where Rye places it's configuration or if you need +to isolate it.

+

Home Folder Structure

+

The .rye home folder contains both user configuration as well as Rye managed state such +as installed toolchains. The following files and folders are placed within the +.rye folder. Note that not all are there always.

+

config.toml

+

This is a configuration file that influences how Rye operates. Today very little configuration +is available there. For the available config keys see Config File.

+

self

+

While Rye is written in Rust, it uses a lot of Python tools internally. These are maintained in +an internal virtualenv stored in this location.

+

py

+

In this folder Rye stores the different toolchains. Normally those are folders +containing downloaded Python distributions, but they can also be symlinks or special reference +files.

+

shims

+

This folder contains shim binaries. These binaries are for instance the python executable +which automatically proxies to the current virtualenv or globally installed tools.

+

Config File

+

The config file config.toml in the .rye folder today only is used to manage defaults. This +is a fully annotated config file:

+
[default]
+# This is the default value that is written into new pyproject.toml
+# files for the `project.requires-python` key
+requires-python = ">= 3.8"
+
+# This is the default toolchain that is used
+toolchain = "cpython@3.11.1"
+
+# This is the default build system that is used
+build-system = "hatchling"
+
+# This is the default license that is used
+license = "MIT"
+
+# This sets the default author (overrides the defaults from git).  The
+# format here is "Name <email>".
+author = "Full Name <email@address.invalid>"
+
+# The dependency operator to use by default for dependencies.  The options are
+# '>=', '~=', and '=='.  The default currently is '>='.  This affects the behavior
+# of `rye add`.
+dependency-operator = ">="
+
+[proxy]
+# the proxy to use for HTTP (overridden by the http_proxy environment variable)
+http = "http://127.0.0.1:4000"
+# the proxy to use for HTTPS (overridden by the https_proxy environment variable)
+https = "http://127.0.0.1:4000"
+
+[behavior]
+# When set to true the `managed` flag is always assumed to be true.
+force-rye-managed = false
+
+# Enables global shims when set to `true`.  This means that the installed
+# `python` shim will resolve to a Rye managed toolchain even outside of
+# virtual environments.
+global-python = false
+
+# When set to `true` enables experimental support of uv as a replacement
+# for pip-tools. Learn more about uv here: https://github.com/astral-sh/uv
+use-uv = false
+
+# Enable or disable automatic `sync` after `add` and `remove`.  This defaults
+# to `true` when uv is enabled and `false` otherwise.
+autosync = true
+
+# Marks the managed .venv in a way that cloud based synchronization systems
+# like Dropbox and iCloud Files will not upload it.  This defaults to true
+# as a .venv in cloud storage typically does not make sense.  Set this to
+# `false` to disable this behavior.
+venv-mark-sync-ignore = true
+
+# a array of tables with optional sources.  Same format as in pyproject.toml
+[[sources]]
+name = "default"
+url = "http://pypi.org/simple/"
+
+

Manipulating Config

+
+

new in 0.9.0

+
+

The configuration can be read and modified with rye config. The +keys are in dotted notation. --get reads a key, --set, --set-int, +--set-bool, or --unset modify one.

+
rye config --set proxy.http=http://127.0.0.1:4000
+rye config --set-bool behavior.force-rye-managed=true
+rye config --get default.requires-python
+
+

For more information see config.

+

Per Project Config

+

For the project specific pyproject.toml config see pyproject.toml.

+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/deps/index.html b/guide/deps/index.html new file mode 100644 index 0000000000..83d826f96b --- /dev/null +++ b/guide/deps/index.html @@ -0,0 +1,1552 @@ + + + + + + + + + + + + + + + + + + + + + + + + Dependencies - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Dependencies

+

Dependencies are declared in pyproject.toml however adding them can be +simplified with the rye add command. In the most simple invocation it adds a regular +dependency, but it can be customized.

+

Adding Basic Dependency

+

To add a regular dependency just invoke rye add with the name of the Python package:

+
rye add Flask
+
+

If you also want to define a version, use a PEP 508 +requirement:

+
rye add "Flask>=2.0"
+
+

For extra/feature dependencies you can either use PEP 508 syntax or use --features:

+
rye add "Flask[dotenv]"
+rye add Flask --features=dotenv
+
+

These dependencies are stored in project.dependencies.

+
+

Note about pre-releases

+

By default add will not consider pre-releases. This means if you add a dependency +that has .dev or similar in the version number you will not find a match. To +consider them, add them with --pre:

+
rye add "Flask==2.0.0rc2" --pre
+
+
+

Development Dependencies

+

For dependencies that should only be installed during development pass --dev

+
rye add --dev black
+
+

These dependencies are stored in the non-standard +tool.rye.dev-dependencies key.

+

To run tools added this way without enabling the virtualenv use rye run:

+
rye run black
+
+

Git / Local Dependencies

+

To add a local or git dependency, you can pass additional parameters like --path +or --git:

+
rye add Flask --git=https://github.com/pallets/flask
+rye add My-Utility --path ./my-utility
+
+

Note that when adding such dependencies, it's necessary to also provide the name +of the package. Additionally for git dependencies all kinds of extra parameters +such as --tag, --rev or --branch are supported.

+

When working with local dependencies it's strongly encouraged to configure a +workspace.

+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/faq/index.html b/guide/faq/index.html new file mode 100644 index 0000000000..15daa87c0b --- /dev/null +++ b/guide/faq/index.html @@ -0,0 +1,1727 @@ + + + + + + + + + + + + + + + + + + + + + + + + FAQ - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

FAQ

+

This section should cover some commonly asked questions. If you do not find an answer +here, consider reaching out to the community.

+

How Do I Install PyTorch?

+

PyTorch requires setting up manual sources as it's not installed via +PyPI. These sources can be set up in pyproject.toml for a +simple project or globally in the config.

+
    +
  • +

    Option 1: pyproject.toml

    +
    [[tool.rye.sources]]
    +name = "pytorch"
    +url = "https://download.pytorch.org/whl/cpu"
    +
    +
  • +
  • +

    Option 2: ~/.rye/config.toml

    +
    [[sources]]
    +name = "pytorch"
    +url = "https://download.pytorch.org/whl/cpu"
    +
    +
  • +
+

Afterwards you can add pytorch as you would expect:

+
rye add torch torchvision torchaudio
+
+

Windows Developer Mode

+

Rye does not require symlinks but it works significantly better with them. On Windows +support for symlinks is restricted to privileged accounts. The reason for this is that +Symlinks were a late addition to Windows and some applications are not developed with +them in mind which can cause misbehavior or in the worst case security issues in those +applications. Symlinks support however is enabled when the "developer mode" is activated +on modern Windows versions.

+

Enabling "developer mode" has changed in later version of Windows. For older versions:

+
    +
  1. Press Win+I to open the settings
  2. +
  3. In the settings dialog click on "Privacy & security"
  4. +
  5. In the "Security" section click on "For developers"
  6. +
  7. Enable the toggle "Developer Mode"
  8. +
  9. In the "Use developer features" dialog confirm by clicking "Yes".
  10. +
+

In more modern versions:

+
    +
  1. Press Win+I to open the settings
  2. +
  3. In the settings dialog click on "System"
  4. +
  5. In the "System" section click on "For developers"
  6. +
  7. Enable the toggle "Developer Mode"
  8. +
  9. In the "Use developer features" dialog confirm by clicking "Yes".
  10. +
+
+What happens if I don't enable it? +

Enabling symlinks is not strictly required as Rye automatically falls back to +hardlinks and junction points. However not having symlinks enabled will ultimately +result in a worse user experience for the following reasons:

+
    +
  • Custom toolchain registration uses proxy files rather than actual symlinks which + means that the executables in the .rye\py path are non executable.
  • +
  • All shims will be installed as hardlinks. This can cause issues when upgrading + Rye while Python is in use. These hardlinks will also continue to point to older + Rye executables creating more hard drive usage.
  • +
  • Virtualenvs will be created with copies rather than symlinks.
  • +
  • Junction points are used where symlinks to directories are otherwise used. Some + tools might accidentally not detect junction points which can cause deletion of + virtualenvs to accidentally also delete or destroy the toolchain behind it.
  • +
+
+

Missing Shared Libraries on Linux

+

The Python builds that Rye uses require a Linux installation compatible to the +Linux Standard Base Core Specification (LSB). Unfortunately not all Linux +distributions are strictly adhering to that specification out of the box. In +particularly the library libcrypt.so.1 is commonly not installed on certain +Linux distributions but the _crypt standard library module depends on it. +Depending on the Linux distributions you need to run different commands to +resolve this:

+
    +
  • archlinux: pacman -S libxcrypt-compat
  • +
  • CentOS/RedHat: dnf install libxcrypt-compat
  • +
+

There have also been reports of an error being generated at installation time +despite libcrypt.so.1 being installed when a different ldd (eg: Homebrew) +shadows the system one. In that case try the installation again after giving +the default one higher priority in the `PATH:

+
export PATH="/usr/bin:$PATH"
+curl -sSf https://rye-up.com/get | bash
+
+

References to Build-Time Paths

+

The prefers using standalone Python builds. As Python historically is not much +accommodating to portable builds there are various limitations still with this +approach. One of them is that built Python distributions capture some absolute +paths and other build-time configuration. These file paths are then often used +by build tools to invoke C compilers. For instance you might run into a compiler +error like error: stdio.h: No such file or directory when building C +extensions. There is no known solution to this problem today other than +registering a non portable toolchain.

+

This issue is inherited from python-build-standalone and more information can +be found in the documentation: References to Build-Time Paths. There is also an open +Rye issue for it: Issue #621.

+

TKinter Support

+

TKinter uses TCL behind the scenes. Unfortunately this also means that some runtime +support is required. This runtime support is provided by the portable Python builds, +however the way TCL is initialized on macOS and Linux won't find these files in +virtualenvs. Newer versions of Rye will automatically export the TCL_LIBRARY +and TK_LIBRARY environment variables for you in a manner very similar to this:

+
import os
+import sys
+os.environ["TCL_LIBRARY"] = sys.base_prefix + "/lib/tcl8.6"
+os.environ["TK_LIBRARY"] = sys.base_prefix + "/lib/tk8.6"
+
+

Python Interactive Prompt Input Messed Up

+

The Python builds that Rye uses are compiled against libedit rather than readline +for licensing reasons. You might run into unicode issues on input as a result of this +due to limitations in libedit. In some cases though you might also discover that +the backspace key does not work or arrow keys don't work as expected. This can be +because the terminfo database cannot be found.

+

For solutions to this issue, read the behavior quirks guide in the +Standalone Python Builds documentation for solutions.

+

Can I use Rye Alongside Other Python Installations?

+

Rye given it's experimental nature does not want to disrupt already existing Python +workflows. As such using it alongside other Python installations is intentionally +supported. Even if the Rye shims come first on the PATH, Rye will automatically +resolve to a different Python installation on the search path when invoked in a +folder that contains a non Rye managed project.

+

As such the answer is a clear yes!

+

Musl/Alpine Support

+

When bootstrapping it can happen that you are running into a confusing error like +"No such file or directory (os error 2)". This can happen on MUSL based Linux +systems like Alpine. The reason for this is that Rye downloads distribution +independent Python interpreters which are not compatible with Linux systems that +do not use glibc. The solution today is to install Python via other means and +to install Rye with a custom RYE_TOOLCHAIN. For more information see +Customized Installation

+

Wheels Appear to be Missing Files

+

You might be encountering missing files in wheels when running rye build and you +are using hatchling. The reason for this is that rye build uses +"build" behind the scenes to build wheels. There +are two build modes and in some cases the wheel is first built from an sdist. So +if your sdists does not include the necessary data files, the resulting wheel will +also be incorrect.

+

This can be corrected by adding the files to the include in the hatch config +for sdists. For instance the following lines added to pyproject.toml will add +the data files in my_package and all the tests to the sdist from which the +wheel is built:

+
[tool.hatch.build.targets.sdist]
+include = ["src/my_package", "tests"]
+
+

Can I Relocate Virtualenvs?

+

Rye very intentionally places the virtualenv (.venv) in the root folder of the +workspace. Relocations of virtualenvs is not supported. This is a very intentional +decision so that tools do not need to deal with various complex alternatives and can +rely on a simple algorithm to locate it. This is a form of convention over configuration +and can also assist editor integrations.

+

There are some known downsides of this. For instance if you are placing your projects +in Dropbox, it would cause this folder to synchronize. As a way to combat this, Rye +will automatically mark the virtualenv with the necessary flags to disable cloud sync +of known supported cloud synchronization systems.

+

For override this behavior you can set the behavior.venv-mark-sync-ignore configuration +key to false.

+

Why Does Rye Contain Trojan "Bearfoos"?

+

Unfortunately Windows likes to complain that Rye contains the trojan "Win32/Bearfoos.A!ml". +This seems to be something that happens to a few programs written in Rust every once in a +while because the compiler spits out some bytes that have been associated with Trojans +written in Rust.

+

It can be ignored. For more information see the discussion Windows Bearfoos +virus associated with rye.

+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/index.html b/guide/index.html new file mode 100644 index 0000000000..71e0469498 --- /dev/null +++ b/guide/index.html @@ -0,0 +1,1481 @@ + + + + + + + + + + + + + + + + + + + + + + + + Introduction - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Introduction

+

Rye is still a very experimental tool, but this guide is here to help you get +started. Before we dive into the installation and basic usage guide it's +important for you to understand what Rye actually is.

+

Rye is a one-stop-shop tool. The idea is that as a Python developer all you +need to know is Rye, because Rye is your start into the experience. As a Rye +user you do not even need to install Python yourself as Rye does this for you. +This means to use Rye, you just need to install Rye, the rest is done by Rye +itself.

+

Once Rye is on your system, it can automatically install Python interpreters +for you, install packages from package indexes, manage virtualenvs behind +the scenes and more.

+
+ +
+ +

Interested? Then head over to Installation to learn about +how to get Rye onto your system. Once that is done, read the Basics +to learn about how Rye can be used.

+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/installation/index.html b/guide/installation/index.html new file mode 100644 index 0000000000..18e944050f --- /dev/null +++ b/guide/installation/index.html @@ -0,0 +1,1859 @@ + + + + + + + + + + + + + + + + + + + + + + + + Installation - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Installation

+

Rye is built in Rust. It can either be manually compiled and installed or it can +be installed from a binary distribution. It has support for Linux, macOS and +Windows.

+

Installing Rye

+

Rye is installed per-user and self manages itself. It will install itself into +a folder in your home directory and manage itself there.

+ +
+
+
+

To install you can run a curl command which will install the right binary for your +operating system and CPU architecture and install it:

+
curl -sSf https://rye-up.com/get | bash
+
+

Alternatively if you don't trust this approach, you can download the latest release +binary. On first run it will install itself.

+ +
gunzip rye-x86_64-linux.gz
+chmod +x ./rye-x86_64-linux
+./rye-x86_64-linux
+
+
+
+

To install you can run a curl command which will install the right binary for your +operating system and CPU architecture and install it:

+
curl -sSf https://rye-up.com/get | bash
+
+

Alternatively if you don't trust this approach, you can download the latest release +binary. On first run it will install itself.

+ +
gunzip rye-aarch64-macos.gz
+chmod +x ./rye-aarch64-macos
+./rye-aarch64-macos
+
+
+
+

To install Rye on windows download the latest release and run the binary. Upon +first run it will install itself. Please note that it's strongly recommended +to have "Developer Mode" activated when using Rye and before starting the +installation. Learn more.

+ +
+

Note

+

Rye does not yet use signed binaries which means that you will need to allow +the execution of the downloaded executable. If there is no obvious way to do so, click +on "More info" on the error message that shows up and then on "Run anyway".

+

Additionally sometimes a Trojan warning about "Bearfoos" is shown. This is a false +positive. For more information see the discussion Windows Bearfoos +virus associated with rye.

+
+
+
+

You need to have Rust and Cargo installed. If you don't have, you can use +rustup to get them onto your machine.

+

Afterwards you can install Rye via cargo:

+
cargo install --git https://github.com/astral-sh/rye rye
+
+
+
+
+ + +

Rye will automatically download suitable Python toolchains as needed. For more +information about this read about toolchains. To install +a specific version download a binary directly +from GitHub.

+

Customized Installation

+

On some platforms there is some limited support for customizing the installation +experience. This for instance can be necessary on certain Linux environments such +as Alpine where the Rye provided Python interpreter is not supported.

+
+
+
+

+The install script that is piped to bash can be customized with some environment +variables:

+
+
RYE_VERSION
+
+

Defaults to latest. Can be set to an explicit version to install a specific one.

+
+
RYE_INSTALL_OPTION
+
+

Can optionally be set to "--yes" to skip all prompts.

+
+
+
RYE_TOOLCHAIN
+
+

Optionally this environment variable can be set to point to a Python +interpreter that should be used as the internal interpreter. If not +provided a suitable interpreter is automatically downloaded.

+

At present only CPython 3.9 to 3.12 are supported.

+
+
RYE_TOOLCHAIN_VERSION
+
+

For Rye 0.22 and later a specific Python version can be picked rather +than the default. This affects the internal toolchain version only. +It's useful for Docker builds where you can set the internal toolchain +to the same as your project to only fetch a single Python.

+

At present only CPython 3.9 to 3.12 are supported.

+
+
+ +

This for instance installs a specific version of Rye without asking questions:

+

curl -sSf https://rye-up.com/get | RYE_VERSION="0.4.0" RYE_INSTALL_OPTION="--yes" bash
+
+

+
+
+

+The install script that is piped to bash can be customized with some environment +variables:

+
+
RYE_VERSION
+
+

Defaults to latest. Can be set to an explicit version to install a specific one.

+
+
RYE_INSTALL_OPTION
+
+

Can optionally be set to "--yes" to skip all prompts.

+
+
+
RYE_TOOLCHAIN
+
+

Optionally this environment variable can be set to point to a Python +interpreter that should be used as the internal interpreter. If not +provided a suitable interpreter is automatically downloaded.

+

At present only CPython 3.9 to 3.12 are supported.

+
+
RYE_TOOLCHAIN_VERSION
+
+

For Rye 0.22 and later a specific Python version can be picked rather +than the default. This affects the internal toolchain version only. +It's useful for Docker builds where you can set the internal toolchain +to the same as your project to only fetch a single Python.

+

At present only CPython 3.9 to 3.12 are supported.

+
+
+ +

This for instance installs a specific version of Rye without asking questions:

+

curl -sSf https://rye-up.com/get | RYE_VERSION="0.4.0" RYE_INSTALL_OPTION="--yes" bash
+
+

+
+
+

The Windows installer has limited support for customizations via environment +variables. To set these you need to run the installer from cmd.exe.

+
+
+
RYE_TOOLCHAIN
+
+

Optionally this environment variable can be set to point to a Python +interpreter that should be used as the internal interpreter. If not +provided a suitable interpreter is automatically downloaded.

+

At present only CPython 3.9 to 3.12 are supported.

+
+
RYE_TOOLCHAIN_VERSION
+
+

For Rye 0.22 and later a specific Python version can be picked rather +than the default. This affects the internal toolchain version only. +It's useful for Docker builds where you can set the internal toolchain +to the same as your project to only fetch a single Python.

+

At present only CPython 3.9 to 3.12 are supported.

+
+
+ +

This for instance installs Rye with a specific toolchain:

+
set RYE_TOOLCHAIN=%USERPROFILE%\AppData\Local\Programs\Python\Python310\python.exe
+rye-x86_64-windows.exe
+
+
+
+
+

Add Shims to Path

+

Once rye is installed you need to add the shims folder into your PATH. +This folder is a folder that contains "shims" which are executables that +Rye manages for you as well as the rye executable itself. For instance any +Python installation managed by Rye will be available via a shim placed there.

+

On macOS or Linux you can accomplish this by adding it to your .profile file +or similar. This step is technically optional but required if you want to be able to +just type python or rye into the shell to pick up the current virtualenv's Python +interpreter. The installer will offer to do this for you automatically. If you +opt-out, or you run a custom shell you will need to do this manually.

+
+
+
+

Rye ships an env file which should be sourced to update PATH automatically.

+
echo 'source "$HOME/.rye/env"' >> ~/.profile
+
+

In some setups .profile is not sourced, in which case you can add it to your +.bashrc:

+
echo 'source "$HOME/.rye/env"' >> ~/.bashrc
+
+
+
+

Rye ships an env file which should be sourced to update PATH automatically.

+
echo 'source "$HOME/.rye/env"' >> ~/.zprofile
+
+

In some setups .zprofile is not sourced, in which case you can add it to your +.zshrc:

+
echo 'source "$HOME/.rye/env"' >> ~/.zshrc
+
+
+
+

Since fish does not support env files, you need to add +the shims directly. This can be accomplished by running this +command once:

+
set -Ua fish_user_paths "$HOME/.rye/shims"
+
+
+
+

Since nushell does not support env files, you need to add +the shims directly. This can be accomplished by adding this to your +env.nu file:

+
$env.PATH = ($env.PATH | split row (char esep) | append "~/.rye/shims")
+
+
+
+

Rye ships an env file which should be sourced to update PATH automatically.

+
echo '. "$HOME/.rye/env"' >> ~/.profile
+
+
+
+

The windows installer normally will automatically register the rye path in the +PATH environment variable. If this does not work you will need to manually +perform the following steps:

+
    +
  1. Press Win+R, enter sysdm.cpl and hit Enter.
  2. +
  3. In the "System Properties" dialog, click the "Advanced" tab.
  4. +
  5. Click on "Environment Variables".
  6. +
  7. In the top list, double click on the Path variable.
  8. +
  9. In the "Edit environment variable" dialog click on "New".
  10. +
  11. Enter %USERPROFILE%\.rye\shims and hit Enter.
  12. +
  13. Click repeatedly on "Move Up" until the newly added item is at the top.
  14. +
  15. Click on "OK" and close the dialog.
  16. +
+

Note that you might need to restart your login session for this to take effect.

+
+
+
+

There is a quite a bit to shims and their behavior. Make sure to read up on shims +to learn more.

+

Shell Completion

+

Rye supports generating completion scripts for Bash, Zsh, Fish or Powershell. Here are some common locations for each shell:

+
+
+
+
mkdir -p ~/.local/share/bash-completion/completions
+rye self completion > ~/.local/share/bash-completion/completions/rye.bash
+
+
+
+
# Make sure ~/.zfunc is added to fpath, before compinit.
+rye self completion -s zsh > ~/.zfunc/_rye
+
+

Oh-My-Zsh:

+
mkdir $ZSH_CUSTOM/plugins/rye
+rye self completion -s zsh > $ZSH_CUSTOM/plugins/rye/_rye
+
+

Then make sure rye plugin is enabled in ~/.zshrc

+
+
+
rye self completion -s fish > ~/.config/fish/completions/rye.fish
+
+
+
+
# Create a directory to store completion scripts
+mkdir $PROFILE\..\Completions
+echo @'
+Get-ChildItem "$PROFILE\..\Completions\" | ForEach-Object {
+    . $_.FullName
+}
+'@ | Out-File -Append -Encoding utf8 $PROFILE
+# Generate script
+Set-ExecutionPolicy Unrestricted -Scope CurrentUser
+rye self completion -s powershell | Out-File -Encoding utf8 $PROFILE\..\Completions\rye_completion.ps1
+
+
+
+
+

Updating Rye

+

To update rye to the latest version you can use rye itself:

+
rye self update
+
+

Uninstalling

+

If you don't want to use Rye any more, you can ask it to uninstall it again:

+
rye self uninstall
+
+

Additionally you should delete the remaining .rye folder from your home directory and +remove .rye/shims from the PATH again (usually by removing the code that sources +the env file from the installation step). Rye itself does not place any data +in other locations. Note though that virtual environments created by rye will +no longer function after Rye was uninstalled.

+

Preventing Auto Installation

+

Rye when launched will normally perform an auto installation. This can be annoying +in certain development situations. This can be prevented by exporting the +RYE_NO_AUTO_INSTALL environment variable. It needs to be set to 1 to disable +the feature.

+
+
+
+
export RYE_NO_AUTO_INSTALL=1
+
+
+
+
export RYE_NO_AUTO_INSTALL=1
+
+
+
+
set RYE_NO_AUTO_INSTALL=1
+
+
+
+
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/publish/index.html b/guide/publish/index.html new file mode 100644 index 0000000000..292340e921 --- /dev/null +++ b/guide/publish/index.html @@ -0,0 +1,1561 @@ + + + + + + + + + + + + + + + + + + + + + + + + Building and Publishing - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Building and Publishing

+

Rye currently uses build to build the package and uses twine to publish it.

+

Build

+

By default, rye will build both the sdist and wheel targets in the dist directory. The command for this is called build.

+
rye build
+
+

You can use the --sdist or --wheel flag to build the specific target, or specify the output directory with --out.

+
rye build --wheel --out target
+
+

If you want to clean the build directory before building, run:

+
rye build --clean
+
+

Publish

+

Rye will publish the distribution files under the dist directory to PyPI by default.

+
rye publish
+
+

You might be asked to input your access token and some other info if needed.

+
No access token found, generate one at: https://pypi.org/manage/account/token/
+Access token:
+
+

You can also specify the distribution files to be published:

+
rye publish dist/example-0.1.0.tar.gz
+
+

--repository

+

Rye supports publishing the package to a different repository by using the --repository and --repository-url flags. For example, to publish to the test PyPI repository:

+
rye publish --repository testpypi --repository-url https://test.pypi.org/legacy/
+
+

--yes

+

You can optionally set the --yes flag to skip the confirmation prompt. This can be useful for CI/CD pipelines.

+
rye publish --token <your_token> --yes
+
+

Rye will store your repository info in $HOME/.rye/credentials for future use.

+

--skip-existing

+

You can use --skip-existing to skip any distribution files that have already been published to the repository. Note that some repositories may not support this feature.

+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/pyproject/index.html b/guide/pyproject/index.html new file mode 100644 index 0000000000..271a84a600 --- /dev/null +++ b/guide/pyproject/index.html @@ -0,0 +1,1733 @@ + + + + + + + + + + + + + + + + + + + + + + + + Python Project - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Python Project (pyproject.toml)

+

Rye tries to avoid a lot of proprietary configuration in the pyproject.toml file but a bit +is necessary. Here are the most important keys that Rye expects:

+

project.dependencies

+

This key is used to manage dependencies. They work exactly like you expect from a regular +pyproject.toml file and in fact Rye changes nothing about this. However Rye is capable +of modifying these entries with the rye add and rye remove commands.

+
[project]
+dependencies = [
+    "mkdocs~=1.4.3",
+    "mkdocs-material~=9.1.12",
+    "pymdown-extensions~=9.11",
+]
+
+

project.scripts

+

This key specifies the scripts that are to be generated and installed into the virtual environment during sync. +These scripts will invoke the configured entry point.

+

[project.scripts]
+my-hello-script = 'hello:main'
+
+This configuration will generate a script my-hello-script that will call the main function of the +hello module.

+

Scripts can be installed using rye sync and run using rye run:

+
$ rye sync
+$ rye run my-hello-script
+Hello from hello!
+
+

tool.rye.dev-dependencies

+

This works similar to project.dependencies but holds development only dependencies. These +can be added here automatically via rye add --dev.

+
[tool.rye]
+dev-dependencies = ["black~=23.3.0"]
+
+

Dev dependencies are installed automatically unless --no-dev is passed to sync.

+

tool.rye.excluded-dependencies

+

This is a special key that contains dependencies which are never installed, even if they are +pulled in as indirect dependencies. These are added here automatically with rye add --excluded.

+
[tool.rye]
+excluded-dependencies = ["cffi"]
+
+

tool.rye.lock-with-sources

+
+

new in 0.18.0

+
+

When this flag is enabled all lock and sync operations in the project or workspace +operate as if --with-sources is passed. This means that all lock files contain the +full source references. Note that this can create lock files that contain credentials +if the sources have credentials included in the URL.

+
[tool.rye]
+lock-with-sources = true
+
+

tool.rye.managed

+
+

new in 0.3.0

+
+

This key tells rye that this project is supposed to be managed by Rye. This key +primarily affects some automatic creation of virtualenvs. For instance Rye +will not try to initialize a virtualenv when using shims without this flag. It +can be forced enabled in the global config.

+
[tool.rye]
+managed = true
+
+

tool.rye.virtual

+
+

new in 0.20.0

+
+

If this key is set to true the project is declared as a virtual project. This is a special +mode in which the package itself is not installed, but only the dependencies are. This is +for instance useful if you are not creating a Python project, but you are depending on Python +software. As an example you can use this to install software written in Python. This key is +set to true when rye init is invoked with the --virtual flag.

+
[tool.rye]
+virtual = true
+
+

For more information consult the Virtual Project Guide.

+

tool.rye.sources

+

This is an array of tables with sources that should be used for locating dependencies. +This lets you use indexes other than PyPI. These sources can also be configured in the +main config.toml config file with the same syntax.

+
[[tool.rye.sources]]
+name = "default"
+url = "http://pypi.org/simple/"
+
+

For more information about configuring sources see Dependency Sources.

+

tool.rye.scripts

+

This key can be used to register custom scripts that are exposed via rye run. Each key is +a script, and each value is the configuration for that script. Normally the value is an object +with different keys with the most important key being cmd which holds the command to execute. +However if only cmd is set, then the object is optional. cmd itself can either be set to a +string or an array of arguments.

+
[tool.rye.scripts]
+# These three options are equivalent:
+devserver = "flask run --app ./hello.py --debug"
+devserver-alt = ["flask", "run", "--app", "./hello.py", "--debug"]
+devserver-explicit = { cmd = "flask run --app ./hello.py --debug" }
+
+

The following keys are possible for a script:

+

cmd

+

The command to execute. This is either a string or an array of arguments. In either case +shell specific interpolation is unavailable. The command will invoke one of the tools in the +virtualenv if it's available there.

+
[tool.rye.scripts]
+devserver = { cmd = "flask run --app ./hello.py --debug" }
+http = { cmd = ["python", "-mhttp.server", "8000"] }
+
+

env

+

This key can be used to provide environment variables with a script:

+
[tool.rye.scripts]
+devserver = { cmd = "flask run --debug", env = { FLASK_APP = "./hello.py" } }
+
+

chain

+

This is a special key that can be set instead of cmd to make a command invoke multiple +other commands. Each command will be executed one after another. If any of the commands +fails, the rest of the commands won't be executed and the chain fails.

+
[tool.rye.scripts]
+lint = { chain = ["lint:black", "lint:flake8" ] }
+"lint:black" = "black --check src"
+"lint:flake8" = "flake8 src"
+
+

call

+

This is a special key that can be set instead of cmd to make a command invoke python +functions or modules. The format is one of the three following formats:

+
    +
  • <module_name>: equivalent to python -m <module_name>
  • +
  • <module_name>:<function_name>: runs <function_name> from <module_name> and exits with the return value
  • +
  • <module_name>:<function_name>(<args>): passes specific arguments to the function
  • +
+

Extra arguments provided on the command line are passed in sys.argv.

+
[tool.rye.scripts]
+serve = { call = "http.server" }
+help = { call = "builtins:help" }
+hello-world = { call = "builtins:print('Hello World!')" }
+
+

tool.rye.workspace

+

When a table with that key is stored, then a project is declared to be a +workspace root. By default all Python projects discovered in +sub folders will then become members of this workspace and share a virtualenv. +Optionally the members key (an array) can be used to restrict these members. +In that list globs can be used. The root project itself is always a member.

+
[tool.rye.workspace]
+members = ["mylib-*"]
+
+

For more information consult the Workspaces Guide.

+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/rust/index.html b/guide/rust/index.html new file mode 100644 index 0000000000..3fba2b38b9 --- /dev/null +++ b/guide/rust/index.html @@ -0,0 +1,1539 @@ + + + + + + + + + + + + + + + + + + + + + + + + Rust Modules - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Rust Modules

+

Rye recommends using maturin to develop Rust Python +extension modules. This process is largely automated and new projects can be created +with rye init.

+

New Project

+
rye init my-project --build-system maturin
+cd my-project
+
+

The following structure will be created:

+
.
+├── .git
+├── .gitignore
+├── .python-version
+├── README.md
+├── pyproject.toml
+├── Cargo.toml
+├── python
+    └── my_project
+        └── __init__.py
+└── src
+    └── lib.rs
+
+

Iterating

+

When you use maturin as a build system then rye sync will automatically build the rust +extension module into your venv. Likewise rye build will use maturin to trigger a +wheel build. For faster iteration it's recommended to use maturin directly.

+

If you want to use other maturin commands such as maturin develop you can install +it as a global tool:

+
rye install maturin
+
+

Note that maturin develop requires pip to be installed into the virtualenv. Before +you can use it you need to add it:

+
rye add --dev pip
+rye sync
+
+

Rye recommends mixed python/rust modules. In that case you can save some valuable +iteration time by running maturin develop --skip-install:

+
maturin develop --skip-install
+
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/shims/index.html b/guide/shims/index.html new file mode 100644 index 0000000000..b9e3a02c3b --- /dev/null +++ b/guide/shims/index.html @@ -0,0 +1,1526 @@ + + + + + + + + + + + + + + + + + + + + + + + + Shims - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Shims

+

After installation Rye places two shims on your PATH: python and python3. These +shims have specific behavior that changes depending on if they are used within a Rye +managed project or outside.

+

Inside a Rye managed project they resolve to the Python interpreter of the virtualenv. +This means that even if you do not enable the virtualenv, you can just run python +in a shell, and it will automatically operate in the right environment.

+

Outside a Rye managed project it typically resolves to your system Python, though you +can also opt to have it resolve to a Rye managed Python installation for you. This is +done so that it's not disruptive to your existing workflows which might depend on the +System python installation.

+

Global Shims

+
+

new in 0.9.0

+
+

To enable global shims, you need to enable the global-python flag in +the config.toml file:

+
rye config --set-bool behavior.global-python=true
+
+

Afterwards if you run python outside of a Rye managed project it will +spawn a Python interpreter that is shipped with Rye. It will honor the +closest .python-version file for you. Additionally you can also +explicitly request a specific Python version by adding +VERSION after +the python command. For instance this runs a script with Python 3.8:

+
python +3.8 my-script.py
+
+
+

Note

+

Selecting a specific Python version this way only works outside of +Rye managed projects. Within Rye managed projects, the version needs +to be explicitly selected via .python-version or with the +requires-python key in pyproject.toml.

+
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/sources/index.html b/guide/sources/index.html new file mode 100644 index 0000000000..655af863c3 --- /dev/null +++ b/guide/sources/index.html @@ -0,0 +1,1655 @@ + + + + + + + + + + + + + + + + + + + + + + + + Dependency Sources - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Dependency Sources

+
+

new in 0.2.0

+
+

Normally Rye loads packages from PyPI only. However it is possible to instruct it to +load packages from other indexes as well.

+

Adding a Source

+

An index can be added to a project or workspace (via pyproject.toml) or into the +global config. Rye will always consult both files where the +pyproject.toml file wins over the global config.

+

Each source needs to have a unique name. The default source is always called default +and out of the box points to PyPI.

+
+
+
+

Add this to ~/.rye/config.toml:

+
[[sources]]
+name = "company-internal"
+url = "https://company.internal/simple/"
+
+
+
+

Add this to pyproject.toml:

+
[[tool.rye.sources]]
+name = "company-internal"
+url = "https://company.internal/simple/"
+
+
+
+
+
+

changed in 0.4.0

+

Sources in the global config are also considered for tool installations.

+
+

Index Types

+

Rye supports different types of sources and also allows overriding the default +PyPI index. If you give another source the name default, PyPI will no longer be +used for resolution.

+
+
+
+
[[sources]]
+name = "company-internal"
+url = "https://company.internal/simple/"
+type = "index"  # this is implied
+
+
+
+
[[sources]]
+name = "company-internal"
+url = "https://company.internal/"
+type = "find-links"
+
+
+
+
[[sources]]
+name = "default"
+url = "https://company.internal/simple/"
+
+
+

Warning

+

Please take note that the default index cannot be of type find-links.

+
+
+
+
+

Source Types

+

The two sources types (index vs find-links) are determined by the underlying pip +infrastructure:

+

index

+

This is a PEP 503 type index as provided +by tools such as PyPI or devpi. It corresponds to +the arguments --index-url or --extra-index-url in pip.

+ +

This is a source that can be of a variety of types and has to point to a file path +or hosted HTML page linking to packages. It corresponds to the --find-links +argument. The format of the HTML page is somewhat underspecified but generally +all HTML links pointing to .tar.gz or .whl files are considered.

+

Index Authentication

+

HTTP basic auth is supported for index authentication. It can be supplied in two +ways. username and password can be directly embedded in the config, or they +can be supplied with environment variables.

+
+
+
+
[[sources]]
+name = "company-internal"
+url = "https://company.internal/simple/"
+username = "username"
+password = "super secret"
+
+
+
+
[[sources]]
+name = "company-internal"
+url = "https://${INDEX_USERNAME}:${INDEX_PASSWORD}@company.internal/simple/"
+
+
+
+
+

SSL/TLS Verification

+

By default a source needs to be SSL/TLS protected. If not, rye will refuse to honor +the source. You can override this by setting verify-ssl to false:

+
[[sources]]
+name = "company-internal"
+url = "http://company.internal/simple/"
+verify-ssl = false
+
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/sync/index.html b/guide/sync/index.html new file mode 100644 index 0000000000..0a6c8dd5bc --- /dev/null +++ b/guide/sync/index.html @@ -0,0 +1,1631 @@ + + + + + + + + + + + + + + + + + + + + + + + + Syncing and Locking - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Syncing and Locking

+

Rye supports two systems to manage dependencies: +uv and +pip-tools. It currently defaults to +pip-tools but will offer you the option to use uv instead. uv will become +the default choice once it stabilzes as it offers significantly better performance.

+

In order to download dependencies rye creates two "lockfiles" (called +requirements.lock and requirements-dev.lock). These are not real lockfiles +but they fulfill a similar purpose until a better solution has been implemented.

+

Whenever rye sync is called, it will update lockfiles as well as the +virtualenv. If you only want to update the lockfiles, then rye lock can be +used.

+

Lock

+

When locking, some options can be provided to change the locking behavior. These flags are +also all available on rye sync.

+

--update / --update-all

+

Updates a specific or all requirements to the latest and greatest version. Without this flag +a dependency will only be updated if necessary.

+
rye lock --update-all
+
+

--features / --all-features

+

Python packages can have extra dependencies. By default the local package that is installed +will only be installed with the default features. If for instance you have an extra dependency +this will only be installed if the feature is enabled.

+
rye add --optional=web flask
+rye lock --features=web
+
+

When working with workspaces, the package name needs to be prefixed with a slash:

+
rye lock --features=package-name/feature-name
+
+

The --features parameter can be passed multiple times and features can also be comma +separated. To turn on all features, the --all-features parameter can be used.

+
rye lock --all-features
+
+

--pre

+

By default updates and version resolution will not consider pre-releases of packages. If you +do want to include those, pass --pre

+
rye lock Flask --pre
+
+

--with-sources

+
+

new in 0.18.0

+
+

By default (unless the tool.rye.lock-with-sources config key is set to true in the +pyproject.toml) lock files are not generated with source references. This means that +if custom sources are used the lock file cannot be installed via pip unless also +--find-links and other parameters are manually passed. This can be particularly useful +when the lock file is used for docker image builds.

+

When this flag is passed then the lock file is generated with references to --index-url, +--extra-index-url or --find-links.

+
rye lock --with-sources
+
+

Sync

+

Syncing takes the same parameters as lock and then some. Sync will usually first do what +lock does and then use the lockfiles to update the virtualenv.

+

--no-lock

+

To prevent the lock step from automatically running, pass --no-lock.

+
rye sync --no-lock
+
+

--no-dev

+

Only sync based on the production lockfile (requirements.lock) instead of the development +lockfile (requirements-dev.lock).

+
rye sync --no-dev
+
+

Limitations

+

Lockfiles depend on the platform they were generated on. This is a known limitation +in pip-tools.

+

For example, if your project relies on platform-specific packages and you generate +lockfiles on Windows, these lockfiles will include Windows-specific projects. +Consequently, they won't be compatible with other platforms like Linux or macOS.

+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/toolchains/cpython/index.html b/guide/toolchains/cpython/index.html new file mode 100644 index 0000000000..c9be79e8aa --- /dev/null +++ b/guide/toolchains/cpython/index.html @@ -0,0 +1,1557 @@ + + + + + + + + + + + + + + + + + + + + + + + + Portable CPython - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Portable CPython

+

Rye is capable (and prefers) to download its own Python distribution over what +you might already have on your computer. For CPython, the +indygreg/python-build-standalone +builds from the PyOxidizer project are used.

+

The motivation for this is that it makes it easy to switch between Python +versions, to have a common experience across different Rye users and to +avoid odd bugs caused by changes in behavior.

+

Unfortunately Python itself does not release binaries (or the right types of +binaries) for all operating systems which is why Rye leverages the portable +Python builds from PyOxidizer.

+

Unlike many other Python versions you can install on your computer are +non-portable which means that if you move them to a new location on your +machine, or you copy it onto another computer (even with the same operating +system) they will no longer run. This is undesirable for what Rye wants to do. +For one we want the same experience for any of the Python developers, no matter +which operating system they used. Secondly we want to enable self-contained +Python builds later, which requires that the Python installation is portable.

+

To achieve this, the Python builds we use come with some changes that are +different from a regular Python build.

+

Limitations

+

The following changes to a regular Python versions you should be aware of:

+
    +
  • +

    libedit instead of readline: unfortunately readline is GPL2 licensed + and this is a hazard for redistributions. As such, the portable Python + builds link against the more freely licensed libedit instead.

    +
  • +
  • +

    dbm.gnu is unavailable. This is a rather uncommonly used module and the + standard library provides alternatives.

    +
  • +
+

Additionally due to how these builds are created, there are some other quirks +you might run into related to terminal support or TKinter. Some of these +issues are collected in the FAQ. Additionally the Python +Standalone Builds have a Behavior Quirks +page.

+

Sources

+

Portable CPython builds are downloaded from GitHub +(indygreg/python-build-standalone/releases) +and SHA256 hashes are generally validated. Some older versions might not +have hashes available in which case the validation is skipped.

+

Usage

+

When you pin a Python version to cpython@major.minor.patch (or just +major.minor.patch) then Rye will automatically download the right version +for you whenever it is needed. If a custom toolchain has already been registered with that name and +version, that this is used instead.

+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/toolchains/index.html b/guide/toolchains/index.html new file mode 100644 index 0000000000..f9db580bc3 --- /dev/null +++ b/guide/toolchains/index.html @@ -0,0 +1,1619 @@ + + + + + + + + + + + + + + + + + + + + + + + + Toolchain Management - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Toolchain Management

+

Rye is unique in that it does not use system Python installations. Instead it downloads +and manages Python installations itself (called toolchains). Today there are +three types of toolchains supported by Rye and they require some understanding:

+ +

Pinning Toolchains

+

To make a project use a specific toolchain write the name of the toolchain into the +.python-version file or use the pin command. For pinning cpython the cpython@ +prefix can be omitted.

+
rye pin cpython@3.11.4
+
+

Pinning a downloadable version means that Rye will automatically fetch it when necessary. +By default, toolchains are pinned to a precise version. This means that even if you +write rye pin cpython@3.11, a very specific version of cpython is written into the +.python-version file. With Rye 0.5.0 onwards it's possible to perform "relaxed" pins:

+
rye pin --relaxed cpython@3.11
+
+

This will then persist 3.11 in the .python-version file and Rye will use the latest +available compatible version for the virtual environment.

+
+

changed in 0.5.0

+

Relaxed pinning with rye pin --relaxed was added.

+
+

Non Native Architectures

+
+

new in 0.14.0

+

Support for fetching and pinning of non-native architectures was added.

+
+

By default, the pin is for the architecture of the running machine. This means that +if you pin cpython@3.11 on a mac with aarch64 architecture, you will use a cpython +interpreter of that CPU architecture. A different architecture can be selected by +adding -{arch} to the python family name. So for instance to force a x86_64 version +you need to pin like this:

+
rye pin cpython-x86_64@3.11
+
+

Note that such custom pins are not reflected in pyproject.toml but only .python-version.

+

Listing Toolchains

+

To see which toolchains are installed, rye toolchain list prints a list:

+

rye toolchain list
+
+
cpython@3.11.1 (C:\Users\armin\.rye\py\cpython@3.11.1\install\python.exe)
+pypy@3.9.16 (C:\Users\armin\.rye\py\pypy@3.9.16\python.exe)
+

+

To see which toolchains can be installed, additionally pass the --include-downloadable:

+
rye toolchain list --include-downloadable
+
+

Fetching Toolchains

+

Generally Rye automatically downloads toolchains, but they can be explicitly fetched +with rye toolchain fetch (also aliased to rye fetch):

+
rye toolchain fetch cpython@3.8.5
+
+

Starting with Rye 0.19.0 the argument to fetch is inferred from the current pin. This means +you can also fetch as follows:

+
rye pin 3.10
+rye fetch
+
+

Toolchains are fetched from two sources:

+ +

Registering Toolchains

+

Additionally, it's possible to register an external toolchain with the rye toolchain register +command.

+
rye toolchain register /path/to/python
+
+

The name of the toolchain is picked based on the interpreter. For instance +linking a regular cpython installation will be called cpython@version, whereas +linking pypy would show up as pypy@version. From Rye 0.5.0 onwards -dbg is +appended to the name of the toolchain if it's a debug build. To override the +name you can pass --name:

+
rye toolchain register --name=custom /path/to/python
+
+

Removing Toolchains

+

To remove an already fetched toolchain run rye toolchain remove. Note that this +also works for linked toolchains:

+
rye toolchain remove cpython@3.8.5
+
+
+

Warning

+

Removing an actively used toolchain will render the virtualenvs that refer to use broken.

+
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/toolchains/pypy/index.html b/guide/toolchains/pypy/index.html new file mode 100644 index 0000000000..140b9f610e --- /dev/null +++ b/guide/toolchains/pypy/index.html @@ -0,0 +1,1531 @@ + + + + + + + + + + + + + + + + + + + + + + + + PyPy - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

PyPy

+

PyPy is supported as alternative Python distribution. +Like the portable CPython builds it's downloaded automatically. The name for +PyPy distributions is pypy.

+

Limitations

+

PyPy has some limitations compared to regular Python builds when it comes to +working with Rye. Most specifically PyPy uses some internal pypi dependencies +and you might notice warnings show up when syching. PyPy also lags behind +regular Python installations quite a bit these days so you likely need to +target older Python packages.

+

Sources

+

PyPy builds are downloaded from +downloads.python.org.

+

Usage

+

When you pin a Python version to pypy@major.minor.patch then Rye will +automatically download the right version for you whenever it is needed. If a +custom toolchain has already been registered +with that name and version, that this is used instead. Note that the version +refers to the PyPy CPython version.

+

That means for instance that PyPy 7.3.11 is identified as pypy@3.9.16 as this +is the Python version it provides. As PyPy also lacks builds for some CPU +architectures, not all platforms might provide the right PyPy versions.

+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/tools/index.html b/guide/tools/index.html new file mode 100644 index 0000000000..82cd15879c --- /dev/null +++ b/guide/tools/index.html @@ -0,0 +1,1556 @@ + + + + + + + + + + + + + + + + + + + + + + + + Tools - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Tools

+

Rye supports global tool installations. This for instance allows you to install +tools like black or ruff globally.

+

Installing Tools

+

Use the rye tools install (aliased to rye +install) command to install a tool globally with a shim:

+
rye install ruff
+
+

Afterwards the tool is installed into ~/.rye/tools/ruff and the necessary shims +are placed in ~/.rye/shims.

+
+

changed in 0.4.0

+

The install command now considers custom sources configured +in the config.toml file. For more information see Dependency Sources.

+
+

Extra Requirements

+

Some tools do not declare all of their dependencies since they might be optional. +In some cases these can be declared by passing extra features to the installer:

+
rye install black --features colorama
+
+

If dependencies are not at all specified, then they can be provided with --extra-requirement. +This is particularly sometimes necessary if the tool uses pkg_resources (part of +setuptools) but forgets to declare that dependency:

+
rye install gradio --extra-requirement setuptools
+
+

Listing Tools

+

If you want to see which tools are installed, you can use rye tools list:

+
rye tools list
+
+
black
+  black
+  blackd
+ruff
+  ruff
+
+

To also see which scripts those tools provide, also pass --include-scripts

+
rye tools list --include-scripts
+
+

Uninstalling Tools

+

To uninstall a tool again, use rye tools uninstall (aliased to rye uninstall):

+
rye uninstall black
+
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/virtual/index.html b/guide/virtual/index.html new file mode 100644 index 0000000000..b79a23d8ea --- /dev/null +++ b/guide/virtual/index.html @@ -0,0 +1,1534 @@ + + + + + + + + + + + + + + + + + + + + + + + + Virtual Projects - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Virtual Projects

+
+

new in 0.20.0

+
+

Virtual projects are projects which are themselves not installable Python +packages, but that will sync their dependencies. They are declared like a +normal python package in a pyproject.toml, but they do not create a package. +Instead the tool.rye.virtual key is set to true.

+

For instance this is useful if you want to use a program like mkdocs without +declaring a package yourself:

+
rye init --virtual
+rye add mkdocs
+rye sync
+rye run mkdocs
+
+

This will create a pyproject.toml but does not actually declare any python code itself. +Yet when synching you will end up with mkdocs in your project.

+

Behavior Changes

+

When synching the project itself is never installed into the virtualenv as it's not +considered to be a valid package. Likewise you cannot publish virtual packages to +PyPI or another index.

+

Limitations

+

Virtual projects can not have optional dependencies. These even if declared are not +installed.

+

Workspaces

+

If a workspace does not have a toplevel package it's +recommended that it's declared as virtual.

+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/guide/workspaces/index.html b/guide/workspaces/index.html new file mode 100644 index 0000000000..8ec14df857 --- /dev/null +++ b/guide/workspaces/index.html @@ -0,0 +1,1534 @@ + + + + + + + + + + + + + + + + + + + + + + + + Workspaces - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Workspaces

+

Workspaces are a feature that allows you to work with multiple packages that +have dependencies to each other. A workspace is declared by setting the +tool.rye.workspace key a pyproject.toml. Afterwards all projects within +that workspace share a singular virtualenv.

+

Declaring Workspaces

+

A workspace is declared by the "toplevel" pyproject.toml. At the very least +the key tool.rye.workspace needs to be added. It's recommended that a glob +pattern is also set in the members key to prevent accidentally including +unintended folders as projects.

+
[tool.rye.workspace]
+members = ["myname-*"]
+
+

This declares a workspace where all folders starting with the name myname- +are considered. If the toplevel workspace in itself should not be a project, +then it should be declared as a virtual package:

+
[tool.rye]
+virtual = true
+
+[tool.rye.workspace]
+members = ["myname-*"]
+
+

For more information on that see Virtual Packages.

+

Syncing

+

In a workspace it does not matter which project you are working with, the entire +workspace is synchronized at all times. This has some untypical consequences but +simplifies the general development workflow.

+

When a package depends on another package it's first located in the workspace locally +before it's attempted to be downloaded from an index. The --all-features flag is +automatically applied to all packages, but to turn on the feature of a specific +package the feature name must be prefixed. For instance to enable the foo extra feature +of the myname-bar package you would need to do this:

+
rye sync --features=myname-bar/foo
+
+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/hooks.py b/hooks.py new file mode 100644 index 0000000000..66011c8237 --- /dev/null +++ b/hooks.py @@ -0,0 +1,7 @@ +import os +import shutil + + +def copy_get(config, **kwargs): + site_dir = config["site_dir"] + shutil.copy("scripts/install.sh", os.path.join(site_dir, "get")) diff --git a/index.html b/index.html new file mode 100644 index 0000000000..a4c9427aff --- /dev/null +++ b/index.html @@ -0,0 +1,1530 @@ + + + + + + + + + + + + + + + + + + + + + + Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + + + + + + + + +
+
+ + + + + + + + + + + + +
+ +

Rye: a Hassle-Free Python Experience

+
+ +

Rye is a comprehensive project and package management solution for Python. +Born from its creator's desire to establish a +one-stop-shop for all Python users, Rye provides a unified experience to install and manages Python +installations, pyproject.toml based projects, dependencies and virtualenvs +seamlessly. It's designed to accommodate complex projects, monorepos and to +facilitate global tool installations. Curious? Watch an introduction.

+

A hassle-free experience for Python developers at every level.

+ +

+ Star +Discuss + Sponsor +

+ +
+

Installation Instructions

+ +
+
+
+

To install you can run a curl command which will install the right binary for your +operating system and CPU architecture and install it:

+
curl -sSf https://rye-up.com/get | bash
+
+

Alternatively if you don't trust this approach, you can download the latest release +binary. On first run it will install itself.

+ +
gunzip rye-x86_64-linux.gz
+chmod +x ./rye-x86_64-linux
+./rye-x86_64-linux
+
+
+
+

To install you can run a curl command which will install the right binary for your +operating system and CPU architecture and install it:

+
curl -sSf https://rye-up.com/get | bash
+
+

Alternatively if you don't trust this approach, you can download the latest release +binary. On first run it will install itself.

+ +
gunzip rye-aarch64-macos.gz
+chmod +x ./rye-aarch64-macos
+./rye-aarch64-macos
+
+
+
+

To install Rye on windows download the latest release and run the binary. Upon +first run it will install itself. Please note that it's strongly recommended +to have "Developer Mode" activated when using Rye and before starting the +installation. Learn more.

+ +
+

Note

+

Rye does not yet use signed binaries which means that you will need to allow +the execution of the downloaded executable. If there is no obvious way to do so, click +on "More info" on the error message that shows up and then on "Run anyway".

+

Additionally sometimes a Trojan warning about "Bearfoos" is shown. This is a false +positive. For more information see the discussion Windows Bearfoos +virus associated with rye.

+
+
+
+

You need to have Rust and Cargo installed. If you don't have, you can use +rustup to get them onto your machine.

+

Afterwards you can install Rye via cargo:

+
cargo install --git https://github.com/astral-sh/rye rye
+
+
+
+
+ +

For the next steps or ways to customize the installation, head over to the detailed +installation guide.

+
+ + + + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/philosophy/index.html b/philosophy/index.html new file mode 100644 index 0000000000..a35345f955 --- /dev/null +++ b/philosophy/index.html @@ -0,0 +1,1879 @@ + + + + + + + + + + + + + + + + + + + + + + Philosophy - Rye + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+ +
+ + + + + + + + + + + +
+
+ + + +
+
+
+ + + + + + + + +
+
+
+ + + + +
+
+ + + + + + + + + + + + +

Philosophy and Vision

+

Rye was built to solve my problems. Here is what was +on my mind when I built it:

+
    +
  • +

    Virtualenvs: while I personally do not like virtualenvs that much, they are + so widespread and have reasonable tooling support, so I chose this over + __pypackages__.

    +
  • +
  • +

    No Default Dependencies: the virtualenvs when they come up are completely void + of dependencies. Not even pip or setuptools are installed into it. Rye + manages the virtualenv from outside the virtualenv.

    +
  • +
  • +

    No Core Non Standard Stuff: Rye (with the exception of it's own tool section + in the pyproject.toml) uses standardized keys. That means it uses regular + requirements as you would expect. It also does not use a custom lock file + format and uses uv and + pip-tools behind the scenes.

    +
  • +
  • +

    No Pip: Rye uses pip, but it does not expose it. It manages dependencies in + pyproject.toml only.

    +
  • +
  • +

    No System Python: I can't deal with any more linux distribution weird Python + installations or whatever mess there is on macOS. I used to build my own Pythons + that are the same everywhere, now I use indygreg's Python builds. + Rye will automatically download and manage Python builds from there. No compiling, + no divergence.

    +
  • +
  • +

    Project Local Shims: Rye maintains a python shim that auto discovers the + current pyproject.toml and automatically operates below it. Just add the + shims to your shell and you can run python and it will automatically always + operate in the right project.

    +
  • +
+

What Could Be?

+

There are a few shortcomings in the Python packaging world, largely as a result of +lack of standardization. Here is what this project ran into over the years:

+
    +
  • +

    No Python Binary Distributions: CPython builds from python.org are completely + inadequate. On some platforms you only get an .msi installer, on some you + literally only get tarballs. The various Python distributions that became popular + over the years are diverging greatly and cause all kinds of nonsense downstream. + This is why this Project uses the indygreg standalone builds. I hope that with + time someone will start distributing well maintained and reliable Python builds + to replace the mess we are dealing with today.

    +
  • +
  • +

    No Dev Dependencies: Rye currently needs a custom section in the pyproject.toml + to represent dev dependencies. There is no standard in the ecosystem for this. It + really should be added.

    +
  • +
  • +

    No Local Dependency Overlays: There is no standard for how to represent local + dependencies. Rust for this purpose has something like { path = "../foo" } + which allows both remote and local references to co-exist and it rewrites them + on publish.

    +
  • +
  • +

    No Exposed Pip: pip is intentionally not exposed. If you were to install something + into the virtualenv, it disappears next time you sync. If you symlink rye to + ~/.rye/shims/pip you can get access to pip without installing it into the + virtualenv. There be dragons.

    +
  • +
  • +

    No Workspace Spec: for monorepos and things of that nature, the Python ecosystem + would need a definition of workspaces. Today that does not exist which forces every + tool to come up with it's own solutions to this problem.

    +
  • +
  • +

    No Basic Script Section: There should be a standard in pyproject.toml to + represent scripts like rye does in rye.tools.scripts.

    +
  • +
+

The Vision

+

This describes of what I envision Python packaging and project management could +look like in an ideal world:

+

The Rust Experience

+

Coming from a Rust environment there are two tools which work together: rustup and +cargo. The first one of those is used to ensure that you have the correct Rust +toolchain on your machine. Rust greatly prefers binary distributions of the language +from the official website over external distributions.

+

cargo is the main entry point to development in Rust. It acts as the tool to +trigger test runs, start the build process, shell out to the documentation building +tool, linters but also things such as workspace management, dependency management and +package publishing.

+

Crucially a very important aspect of the Rust development experience is the strong +commitment to semver and the built-in support for it. This goes very deep. The +resolver for instance will deduplicate matching dependencies throughout the graph. +This means that if four libraries depend on libc@0.2, they will all resolve to +that dependency. However if another need arises for libc@1.0, then it's possible +for the dependency graph to result in both being loaded!

+

The ecosystem greatly depends on this. For instance when a new major release is made +of a very core library, in some cases extra care is taken to unify the now incompatible +versions by re-exporting core types from the newer to the older version. Thus it's +for instance possible for important-lib@0.2.32 to depend on +important-lib@1.0 internally so it can make the transition easier.

+

Additionally Rust heavily leverages lockfiles. Whenever you compile, the dependencies +are locked in place and future builds reuse the same dependency versions unless you +update.

+

Most importantly though the Rust ecosystem has embraced rustup and cargo that the +vast majority of people are using these tools on a daily basis. Even developers who +pick other tools like buck, are still using cargo regularly.

+

Going Python

+

Rye wants to explore if such an experience is possible with Python. I believe it can! +There is quite a lot of the ecosystem that can be leveraged for this purpose but there +is even more that would need to be built.

+

Important note: when you read "rye" in the context of the document it talks about +what a potential tool like rye could be. It might as well be that one of the many +tools that exist today, turn into that very tool that is described here.

+

My sentiment is that unless "the one tool" can emerge in the Python world, the +introduction of yet another tool might be a net-negative to the ecosystem. Plenty of +tools have been created over the years, and unfortunately it hasn't been able to +rally the majority of the Python community behind any tool. I do however believe it is +possible.

+

Bootstrapping Python

+

I believe the right approach is that >95% of users get a Python distribution via rye +and not to have rye pick up a system installed Python distribution. There are good +reasons for using a system Python installation, but it should be the exception not the +rule. Most importantly because a Python distribution that rye puts in place can be +made to have reliable and simple rules that do not differ between systems.

+

A huge cause of confusion and user frustration currently comes from Linux distribution +specific patches on top of Python that break tools and change behavior, particularly +in the python packaging ecosystem.

+

Bootstrapping Python via an independent tool has other benefits as well. It for instance +allows much easier cross-python version testing via tox or CI.

+

What needs to be done:

+
    +
  • Provide widely available Python builds, with largely standardized structure + retrievable from the internet. PEP 711 is a step + in that direction.
  • +
+

A Stronger Resolver

+

Today there are a ton of different resolvers in the Python ecosystem. Pip has two, poetry +has one, pdm has one, different independent Python and Rust resolvers exist on top of that. +Resolvers are important, but unfortunately, there are both too many and too many issues with +the existing ones. Here is what I believe a resolver needs to be able to accomplish:

+
    +
  • +

    Allow resolving across markers: most resolvers in the Python ecosystem today can only + resolve for the current interpreter and platform (eg: pip, pip-tools). This means it cannot + create a resolution that is equally valid for a different platform. In part this is + a problem because of how environment markers in Python are defined. They allow a level of + expressiveness that cannot be reflected by most tools, however a subset could be supported.

    +
  • +
  • +

    Multi-version resolution support: this is a bit foreshadowing, but I believe for a + variety of reasons it needs to be possible for a resolver to not unify all requirements + to a single version, but to support multiple independent resolutions across major versions + of libraries. A future resolver should be able to permit package==2.0 and package==1.1 + to both be resolved for different parts of the tree.

    +
  • +
  • +

    Resolver API: access to the resolver is important. For editor plugins, or custom + tools it's always necessary to be able to resolve packages. For instance if you want + something as trivial as "add latest supported version of 'flask' to my pyproject.toml" + you need to be able to work with the resolver.

    +
  • +
  • +

    Filters: I strongly believe that a good resolver also needs a filter on top. For + instance it must be possible for a developer to restrict the resolver to stay within the + bounds of the target Python version and to never upgrade into a tree containing Python + versions that are too new. Likewise for supply chain safety a resolver should be able to + restrict itself to a set of vetted dependencies.

    +
  • +
+

What needs to be done:

+
    +
  • Create a reusable resolver that can be used by multiple tools in the ecosystem.
  • +
  • Make the resolver work with the proposed metadata cache
  • +
  • Expose the resolver as API for multiple tools to use.
  • +
  • Add a policy layer into the resolver that can be used to filter down the dependencies + before use.
  • +
+

Metadata Caches

+

Because of the rather simplistic nature of Python packages and package indexes a resolver +will always be restricted by the metadata that it can reliably pull. This is particularly +bad if the system needs to fall back to sdist uploads which in the worst case requires +executing python code to determine the dependencies, and those dependencies might not even +match on different platforms.

+

However this is a solvable problem with sufficient caching, and with the right design for +the cache, this cache could be shared. It might even be quite interesting for PyPI to +serve up "fake" metadata records for popular sdist only packages to help resolvers. +This might go a long way in improving the quality of the developer experience.

+

What needs to be done:

+
    +
  • Local metadata caches are added for the resolver to use
  • +
  • PyPI gains the ability to serve dependency meta data
  • +
+

Lockfiles

+

It's unclear if a standard can emerge for lock files given the different requirements, but a +Python packaging solution needs to have support for these. There are a lot of different +approaches to lockfiles today (poetry and pdm for instance have them) but it's not entirely +clear to me that the way they are handled today is sufficiently pragmatic to enable a tool +that is based on lockfiles to get majority adoption.

+

The reason in part relates the suboptimal situation with resolvers (eg: large projects can +take ten minutes or longer to dependency check in poetry), on the other hand however also +because of the reality of how dependencies are currently declared. For instance certain +libraries will "over" depend on third party libraries, even if they are not needed for a +developer. These pulled in dependencies however will still influence the resolver.

+

Most importantly a good lockfile also covers platforms other than the current developer's +machine. This means that if a project supports Windows and Linux, the lockfile should be +handling either dependency trees. This is what cargo accomplishes today, but cargo has a +a much simpler problem to solve here because it has perfect access to package metadata which +resolvers in Python do not have today. What is also problematic in Python is that certain +parts of the dependency tree can be version dependent. In Rust a library A either depends +on library B or it does not, but it does not depend on it conditional to a Python version.

+

The total expressiveness of Python dependencies is challenging. The lack of good metadata +access for the resolver combined with the ability to make dependencies optional conditional +to the Python version is tricky by itself. The complexity however is compounded by the +fact that the resolver needs to come to a solution that can only result in a single resolved +version per package.

+

What needs to be done:

+
    +
  • Experiment with a restricted lock format that satisfies a subset of what markers provide + today, that strikes a good balance.
  • +
  • Provide lockfile support as part of the resolver library.
  • +
+

Upper Bounds & Multi Versioning

+

Resolving Python dependencies is particularly challenging because a single solution must be +found per package. A reason this works at all in the Python ecosystem is that most libraries +do not set upper bounds. This means that they will be eagerly accepting future libraries even +at the cost of not supporting them. That's largely possible because Python is a dynamic +language and a lot of flexibility is usually possible here. However with increased utilization +of type information in the Python world, and maybe with stronger desires for proper locking, +it might be quite likely that upper version bounds become more common.

+

Once that happens however, the Python ecosystem will quite quickly run into blocking future +upgrades until the entire dependency graph has moved up which creates a lot of friction. +Other ecosystems have solved this problem by strictly enforcing semver semantics onto packages +and by permitting multiple semver incompatible libraries to be loaded simultaneously. While +usually a library is only allowed to permit on a single version of a dependency, that dependency +can exist in different versions throughout the dependency tree.

+

In Python there is a perceived worry that this cannot be accomplished because of how site-packages, +PYTHONPATH and sys.modules works. However I believe these to be solvable issues. On the one +hand because .pth files can be used to completely change how the import system works, secondly +because the importlib.metadata API is strong enough these days to allow a package to resolve +it's own metadata. The combination of the two can be used to "redirect" imports in sys.modules +and import statements to ensure that if a library imports a dependency of itself, it ends up with +the right version.

+

What needs to be done:

+
    +
  • Add a new metadata key to pyproject.toml that declares that a package supports multi-versioning
  • +
  • Enforce semver semantics on multi-version dependencies
  • +
  • Provide an import hook that provides multi-version imports as part of Rye
  • +
  • Relax the resolver to permit multiple solutions for multi-version dependencies
  • +
+

Workspaces and Local / Multi Path References

+

With growing development teams one of the most frustrating experiences is the inability to +break up a monolithic Python module into smaller modules without having to constantly publish +minor versions to a package index. The way the Rust ecosystem deals with this issue is two-fold: +on the one hand Rust supports workspaces natively. Workspaces share dependencies and the +resolver results. The equivalent in Python would be that a workspace shares a virtualenv +across all of the projects within in. The second way in which Rust solves this problem is +to permit a dependency to both support declaration of the package name, index but also local +reference.

+

While also Rust does not permit a crate to be published to a package index with references to +packages outside of the index, a separate rewrite step kicks in ahead of publish to clean out +invalid dependency references. If no valid reference remains, the package will not publish.

+

What needs to be done:

+
    +
  • requirement declarations need to be expanded to support defining the name of the index where + they can be found, and optional local path references.
  • +
+

Every Project in a Virtualenv

+

While virtualenv is not my favorite tool, it's the closest we have to a standard. I proposed +that there is always one path for a virtualenv .venv and when Rye manages it, users should +not interact with it manually. It's at that point rye's responsibility to manage it, and it +shall manage it as if it was a throw-away, always re-creatable scratch-pad for dependencies.

+

Preferably over time the structure of virtualenvs aligns between different Python versions +(eg: Windows vs Linux) and the deeply nested lib/py-ver/site-packages structure is flattened +out.

+

What needs to be done:

+
    +
  • Agree on a name for where managed virtualenvs are placed (eg: .venv in the workspace root)
  • +
+

Dev and Tool Dependencies

+

Another topic that is currently unresolved across tools in the ecosystem is how to work with +dependencies that are not used in production. For instance it's quite common that a certain +dependency really only matters on the developer's machine. Today pdm and some other tools +have custom sections in the pyproject.toml file to mark development dependencies, but there +is no agreement across tools on it.

+

What needs to be done:

+

There needs to be an agreed upon standard for all tools. See this discussion

+

Opinionated Defaults

+

Python against PEP-8's wishes just has too many ways in which things can be laid out. There +should be a much stronger push towards encouraging common standards:

+

What needs to be done:

+
    +
  • Rye shall ship with the one true formatter
  • +
  • Rye shall ship with the one true linter
  • +
  • Rye shall always create a preferred folder structure for new projects
  • +
  • Rye shall loudly warn if package-foo does not provide a package_foo module
  • +
+

Existing Tools

+

Some of the existing tools in the ecosystem are close, and there is a good chance that some +of these might be able to combine forces to create that one-true tool. I hope that there +is enough shared interest, that we don't end up with three tools that all try to be Rye.

+ + + + + + +
+
+ + + + +
+ + + +
+ + + +
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 0000000000..dbbeda967e --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Welcome","text":"Rye: a Hassle-Free Python Experience

Rye is a comprehensive project and package management solution for Python. Born from its creator's desire to establish a one-stop-shop for all Python users, Rye provides a unified experience to install and manages Python installations, pyproject.toml based projects, dependencies and virtualenvs seamlessly. It's designed to accommodate complex projects, monorepos and to facilitate global tool installations. Curious? Watch an introduction.

A hassle-free experience for Python developers at every level.

Star Discuss Sponsor

Installation Instructions

LinuxmacOSWindowsCompile Yourself

To install you can run a curl command which will install the right binary for your operating system and CPU architecture and install it:

curl -sSf https://rye-up.com/get | bash\n

Alternatively if you don't trust this approach, you can download the latest release binary. On first run it will install itself.

  • rye-x86_64-linux.gz for 64bit Intel computers
  • rye-aarch64-linux.gz for 64bit ARM computers
gunzip rye-x86_64-linux.gz\nchmod +x ./rye-x86_64-linux\n./rye-x86_64-linux\n

To install you can run a curl command which will install the right binary for your operating system and CPU architecture and install it:

curl -sSf https://rye-up.com/get | bash\n

Alternatively if you don't trust this approach, you can download the latest release binary. On first run it will install itself.

  • rye-aarch64-macos.gz for M1/M2 Macs
  • rye-x86_64-macos.gz for Intel Macs
gunzip rye-aarch64-macos.gz\nchmod +x ./rye-aarch64-macos\n./rye-aarch64-macos\n

To install Rye on windows download the latest release and run the binary. Upon first run it will install itself. Please note that it's strongly recommended to have \"Developer Mode\" activated when using Rye and before starting the installation. Learn more.

  • rye-x86_64-windows.exe for 64bit Intel Windows
  • rye-x86-windows.exe for 32bit Intel Windows

Note

Rye does not yet use signed binaries which means that you will need to allow the execution of the downloaded executable. If there is no obvious way to do so, click on \"More info\" on the error message that shows up and then on \"Run anyway\".

Additionally sometimes a Trojan warning about \"Bearfoos\" is shown. This is a false positive. For more information see the discussion Windows Bearfoos virus associated with rye.

You need to have Rust and Cargo installed. If you don't have, you can use rustup to get them onto your machine.

Afterwards you can install Rye via cargo:

cargo install --git https://github.com/astral-sh/rye rye\n

For the next steps or ways to customize the installation, head over to the detailed installation guide.

"},{"location":"changelog/","title":"Changelog","text":"

Here you can find all the released changes to Rye. If you want to also see the in-development changes that were not released yet, refer to the CHANGELOG.md file in the repository.

"},{"location":"changelog/#0270","title":"0.27.0","text":"

Released on 2024-02-26

  • rye now uses uv to bootstrap its internal packages and tools. #754

  • rye no longer fails if an incorrect VIRTUAL_ENV environment variable is exported. #766

  • Added latest Python builds. #771

  • When uv is used the prompt is now set to the project name. #773

  • Allow rye fetch --force to force re-fetch a downloaded toolchain. #778

  • Fixed a panic when adding a package to a virtual project. #783

  • Bumped uv to 0.1.11. #790

"},{"location":"changelog/#0260","title":"0.26.0","text":"

Released on 2024-02-23

  • init now supports --script and --lib to generate a script or library project. #738

  • Fixed rye config --show-path abort with an error. #706

  • Bumped uv to 0.1.9. #719, #740, #746

  • Bumped ruff to 0.2.2. #700

  • Prevent rye toolchain remove from removing the currently active toolchain. #693

  • Sync latest PyPy releases. #683

  • Fixes an issue where when uv is enabled, add did not honor custom sources. #720

  • When uv is enabled, rye will now automatically sync on add and remove. #677

  • Rename rye tools list flags: -i, --include-scripts to -s, --include-scripts and -v, --version-show to -v, --include-version. #722

"},{"location":"changelog/#0250","title":"0.25.0","text":"

Released on 2024-02-19

  • Improved the error message if config is invoked without arguments. #660

  • Bump uv to 0.1.5. #665, #675, #698

  • When uv is enabled, rye add now uses uv instead of unearth internally. #667

  • The installer now has slightly better wording for what the shims are doing. #669

  • uv can now also be enabled on windows. #675

  • Removed the unsupported and un-used arch parameter from fetch. #681

  • Fixed the -q parameter not working for the init command. #686

  • rye tools list shows broken tools if the toolchain was removed. #692

  • Configure the ruff cache directory to be located within the workspace root. #689

  • Use default toolchain to install tools. #666

  • rye --version now shows if uv is enabled. #699

"},{"location":"changelog/#0240","title":"0.24.0","text":"

Released on 2024-02-15

  • Added new rye list command and deprecated rye show --installed-deps which it replaces. #656

  • Added experimental support for uv. #657

"},{"location":"changelog/#0230","title":"0.23.0","text":"

Released on 2024-02-13

  • When behavior.venv-mark-sync-ignore is set to false and the file system does not support extended attributes, no longer will a warning be printed. #633

  • Fixed a bug that caused warnings about unsupported operations to be shown on Linux. #634

  • The venv sync marker is now only updated when a new virtualenv is created. #638

  • Lockfiles now contain annotations. #643

"},{"location":"changelog/#0220","title":"0.22.0","text":"

Released on 2024-02-09

  • Virtual envs managed by Rye will now by default be marked to not sync to known cloud storage systems (Dropbox and iCloud). #589

  • Fixed a bug where pip-tools sometimes did not get initialized. #596

  • Rye now prefers installed toolchains over newer latest toolchains unless a precise pin is used. #598

  • Removed the non functional shell command. #602

  • Upgraded internal unearth dependency which resolved an issue where rye add tensorflow would not work. #614

  • The installer now supports RYE_TOOLCHAIN_VERSION. #606

  • rye init will no longer create packages with leading digits. #616

  • Rye now statically links vcruntime on Windows which no longer requires the vs redist to be installed. #622

  • rye show now prints out which sources are configured for a project. #631

"},{"location":"changelog/#0210","title":"0.21.0","text":"

Released on 2024-02-03

  • rye fetch now is able to fetch impliciit version in all cases. Previously global shims were not properly defaulted which required the user to be explicit with the fetch request. #574

  • The rye installer now prompts for the default toolchain version if global shims are enabled. #576

  • The internal Python version was bumped to 3.12. #576

  • The installer now can automatically add Rye to PATH on most UNIX environments. #580

"},{"location":"changelog/#0200","title":"0.20.0","text":"

Released on 2024-02-01

  • Improved the error message when an update could not be performed because files are in use. #550

  • Rye now supports virtual projects. These are themselves not installed into the virtualenv but their dependencies are. #551

  • Update the Python internals (python external dependencies) to new versions. #553

  • Update to newer versions of pip tools. For Python 3.7 6.14.0 is used, for new Python versions 7.3.0 is used. #554

  • Added rye fmt and rye lint commands to format and lint with the help of Ruff. #555

  • Restore cursor state on Ctrl-C. This fixes some issues where in rare cases the cursor would disappear even after shutting down rye. #564

  • Upon installation Rye now prompts if global shims should be enabled. #566

  • Add a warning about bugs to the shell command until the behavior has been fixed. #567

"},{"location":"changelog/#0190","title":"0.19.0","text":"

Released on 2024-01-21

  • Improved the behavior of rye fetch. When invoked without arguments it will now try to fetch the version of the requested Python interpreter. Specifically this combining pin and fetch work in a much simplified manner. #545

  • Fixed an issue where rye init would pin a much too specific version in the .python-version file that is generated. #545

  • On Windows the PATH is now automatically adjusted on install and uninstall. This means that manually adding the rye folder to the search path is no longer necessary. #483

  • Fixed a regression in 0.18 that caused the add command to fail. #547

"},{"location":"changelog/#0180","title":"0.18.0","text":"

Released on 2024-01-20

  • Incorporate new Python builds. #535

  • Disable revocation checks on windows to support corporate MITM proxies. #537

  • Detect when a virtualenv relocates and automatically re-create it on sync. #538

  • Added lock --with-sources, sync --with-sources and the new rye.tool.lock-with-sources config. Passing this will ensure that source references are included in the lock files. #540

  • When using global python shims, the .python-version file is now correctly picked up in all cases. #541

  • Added a helpful message if someone attempts to run the non existing rye list command. At a later point there should be a real listing command that can print out the dependencies. Today the only option is the --installed-deps option on the show command which spits out dependencies in the format of the lockfile. #543

  • The installer will no longer attempt to symlink targets which are not valid executables on the platform. This works around some issues with Packages that would prevent to install such as changedetection.io. #542

"},{"location":"changelog/#0170","title":"0.17.0","text":"

Released on 2024-01-15

  • Fixed default generated script reference. #527

  • Correctly fall back to home folder if HOME is unset. #533

"},{"location":"changelog/#0160","title":"0.16.0","text":"

Released on 2023-12-17

  • By default a script with the name of the project is now also configured. #519

  • Rye now configures hatchling better in rye init so that it works with hatchling 1.19 and later. #521

  • Rye now detects the dummy Python shim that starts the windows store and refuses to consider it. #486

"},{"location":"changelog/#0152","title":"0.15.2","text":"

Released on 2023-10-04

  • Fixed the updater not replacing the python shim correctly on Linux.
"},{"location":"changelog/#0151","title":"0.15.1","text":"

Released on 2023-10-03

  • Fixed the updater not replacing the python3 shim correctly.
"},{"location":"changelog/#0150","title":"0.15.0","text":"

Released on 2023-10-03

  • Added support for Python 3.12. #462
"},{"location":"changelog/#0140","title":"0.14.0","text":"

Released on 2023-10-01

  • Add support for fetching alternative CPU architectures. #447

  • The order of git submodule initialization was changed. This improves the automatic author detection when includeIf is used. #443

  • The linux shim installer code will no longer fall back to symlinks when a hardlink cannot be created. This is done as a symlinked shim will not ever function correctly on Linux. This prevents the shim executables like python to instead act as if they are rye. The fallback behavior is now to copy the executable instead. #441

  • The installer now detects fish and will spit out additional instructions for configuring the shell.

  • Fix the wrong behavior when bump version. #454

"},{"location":"changelog/#0130","title":"0.13.0","text":"

Released on 2023-08-29

  • Add a python3 shim on windows. Previously entering python3 in the command line would always bring up the windows store python proxy even when global shims were enabled. As virtualenvs do not support the python3 executable on windows, the internal shim handling is now also changed so that trying to launch python3 will fall back to python. This makes it possible to run maturin build.

  • Add maturin build command to start a new maturin PyO3 project.

"},{"location":"changelog/#0120","title":"0.12.0","text":"

Released on 2023-08-27

  • Improve handling of the pth files for TCL on pypy. #409

  • The rye tools list command now accepts -v to also print out the versions of the installed tools. #396

  • Fixed parsing of versions by rye version. #397

  • Improved the help message for rye init. #401

  • The email address now defaults to a syntactically valid email address if not known to prevent errors with some build tools.

  • Added new Python versions.

  • The rye installer now detects NOEXEC temporary folders and prints out a more helpful error message. #394

  • Fixed an issue where the author email was incorrectly detected. #382

  • The prompt of new virtualenvs is now set to the project name. #383

"},{"location":"changelog/#0110","title":"0.11.0","text":"

Released on 2023-07-18

  • Added new Python versions.

  • Added a new config key default.author to configure the default author that should be set. This overrides the default author that is normally loaded from the git config. #377

  • When importing with rye init and no src folder exists, it will not be created. #375

  • Added support for shell command on Windows. #363

  • Pin down pip to an older version to avoid issues with an incompatible pip-tools version. This does not yet update pip-tools to 7.0 as there are significant regressions in 7.x. #374

  • The version command can show dynamic versions now. #355

  • rye add now properly checks some incompatible argument combinations. #347

  • There is now more toolchain validation. This better supports cases where rye was interrupted during sync. #351

"},{"location":"changelog/#0100","title":"0.10.0","text":"

Released on 2023-07-07

  • Fixed a bug with rye init not operating correctly due to a argument conflict. #346

  • Scripts now support a PDM style call script type. #345

  • The init command is now capable of importing existing projects. #265

  • Fixed the global shim behavior on Windows. #344

"},{"location":"changelog/#090","title":"0.9.0","text":"

Released on 2023-06-21

  • The internal Rye Python version is now 3.11.

  • Rye now emits most messages, most of the time to stdout rather than stderr. #342

  • rye add now accepts --pin to let one override the type of pin to use. #341

  • Added rye config to read and manipulate the config.toml file. #339

  • Added support for the new behavior.global-python flag which turns on global Python shimming. When enabled then the python shim works even outside of Rye managed projects. Additionally the shim (when run outside of Rye managed projects) supports a special first parameter +VERSION which requests a specific version of Python (eg: python +3.8 to request Python 3.8). #336

  • Renamed the config key default.dependency_operator to default.dependency-operator and behavior.force_rye_managed to behavior.force-rye-managed. #338

"},{"location":"changelog/#080","title":"0.8.0","text":"

Released on 2023-06-18

  • Rye for now prefers >= over ~= for newly added dependencies.

  • The workspace member declaration is now platform independent. If members is now explicitly set to an empty list it will not fall back to auto discovery. #331

  • rye add now pins versions with == instead of ~= when the version of the package does not use at least two components. This means that for instance it will now correctly use openai-whisper==20230314 rather than openai-whisper~=20230314 which is not actually satisfiable. #328

  • rye install now lets you install dependencies into the tool's virtualenv during installation that are undeclared via the new --extra-requirement option. #326

  • Improved handling of relative path installations by setting PROJECT_ROOT the same way as PDM does. #321

  • Workspaces will now never discover pyproject.toml files in any dot directories. (Name starting with .) #329

  • Fixed rye build not working correctly on Windows. #327

"},{"location":"changelog/#070","title":"0.7.0","text":"

Released on 2023-06-12

  • rye sync and rye lock now accept --pyproject. #296

  • Added JSON output to rye toolchain list by adding --format=json. #306

  • rye version can bump version by --bump option now. #298

  • Fixed members not handled correctly in workspaces. #300

  • Add --clean for build command. #297

  • Fixed an issue where pip was not invoked from the right working directory causing issues for workspace installations. #292

  • rye init now accepts --private to set the Private :: Do Not Upload classifier that prevents uploads to PyPI. #291

"},{"location":"changelog/#060","title":"0.6.0","text":"

Released on 2023-06-03

  • Add version subcommand for rye. #285

  • Fixed rye pin pinning the wrong version. #288

  • Calling rye init on the root directory no longer fails. #274

  • rye run, show, pin, shell and build now take a --pyproject argument. #232

"},{"location":"changelog/#050","title":"0.5.0","text":"

Released on 2023-05-31

  • Rye will no longer enforce a downloaded interpreter for the internal toolchain. If one has been registered that is compatible it will be used. Additionally the installer now supports the RYE_TOOLCHAIN environment variable which allows a user to supply an already existing Python interpreter at install time. #267

  • The publish command now supports --yes to disable prompts. #270

  • When a Python debug build (Py_DEBUG) is registered as custom toolchain, -dbg is automatically appended to the name by default. #269

  • lto+pgo builds are now preferred for the Python toolchain builds when available. #268

  • It's now possible for .python-version to request partial Python versions in which case the latest available is used. In particular this means that a version like 3.10 can be written into .python-version rather than 3.10.11. This can be accomplished by invoking pin with the new --relaxed flag. #255

  • Workspaces will no longer discover pyproject.toml files in virtualenvs or .git folders. #266

  • Adding or removing dependencies with add or remove now reformats the dependencies array in the pyproject.toml file to multi-line with trailing commas. This should result in significantly better diffing behavior out of the box. #263

  • Default build-system and license can be specified in global config. #244

  • Fixed an issue where the init command would not let you create flit based projects. #254

  • Resolve an error (\"No such file or directory\") shown after updates on Linux machines. #252

  • The built-in updater now validates checksums of updates when updates have SHA-256 hashes available. #253

  • init now accepts --no-pin to not create a .python-version file. #247

"},{"location":"changelog/#040","title":"0.4.0","text":"

Released on 2023-05-29

  • Releases starting with 0.4.0 onwards are published with SHA256 checksum files for all release assets. These files are not yet validated by the installer or updater however.

  • The install command can now install tools from custom indexes. #240

  • Virtualenvs on Unix are now created with a hack to pre-configure TCL and TKinter. #233

  • Fix invalid version error when using rye init with custom toolchain. #234

  • Failed tool installations now properly clean up. #225

  • Correctly swap the rye executable on windows when performing an update to a git version via self update.

"},{"location":"changelog/#030","title":"0.3.0","text":"

Released on 2023-05-27

  • Support retrieving username and repository-url from credentials if not provided for the publish command. #217

  • The installer now validates the availability of shared libraries on Linux with ldd and emits an error with additional information if necessary shared libraries are missing. #220

  • It's now possible to configure http and https proxies. #215

  • If a package is not found because it only has matching pre-releases, a warning is now printed to tell the user to pass --pre. #218

  • Add --username parameter for rye publish. #211

  • The shims are now more resilient. Previously a pyproject.toml file caused in all cases a virtualenv to be created. Now this will only happen when the rye.tool.managed flag is set to true. The old behavior can be forced via the global config. #212

"},{"location":"changelog/#020","title":"0.2.0","text":"

Released on 2023-05-23

  • Resolved a bug where on Windows hitting the shift key (or some other keys) in confirm prompts would cause an error.

  • The installer on Windows now warns if symlinks are not enabled and directs the user to enable developer mode. The --version output now also shows if symlinks are available. #205

  • Support auto fix requires-python when there is a conflict. #160

  • Added support for custom indexes. #199

  • rye add no longer complains when a local version information is in the version. #199

"},{"location":"changelog/#012","title":"0.1.2","text":"

Released on 2023-05-22

  • Fixed dev-dependencies not being installed when using workspace. #170

  • init no longer creates invalid flit config. #195

  • Support direct references when adding a package. #158

  • Fixed a bug with uninstall on Unix platforms. #197

"},{"location":"changelog/#011","title":"0.1.1","text":"

Released on 2023-05-18

  • The installer on windows will now ask for a key to be pressed so it does not close the window without information. #183

  • Fixed an issue on macOS where the installer would die with \"os error 24\" when directly piped to bash. #184

"},{"location":"changelog/#010","title":"0.1.0","text":"

Released on 2023-05-17

  • Rye now comes with binary releases for some platforms.

  • A new self uninstall command was added to uninstall rye and the new self update command updates to the latest release version.

  • Rye now includes a publish command for publishing Python packages to a package repository. #86

  • Script declarations in pyproject.toml now permit chaining and custom environment variables. #153

  • Added tools install and tools uninstall as aliases for install and uninstall and added tools list to show all installed tools.

  • Rye is now capable of downloading a selected set of PyPy releases. To do so use rye pin pypy@3.9.16 or any other supported PyPy release.

  • Custom cpython toolchains are now registered just as cpython rather than custom-cpython.

  • Rye now supports Python down to 3.7.

  • Rye's self command now includes a completion subcommand to generate a completion script for your shell.

  • The downloaded Python distributions are now validated against the SHA-256 hashes.

  • Rye now builds on windows. This is even more experimental though than support for Linux and macOS.

  • Added --features and --all-features for lock and sync.

  • Rye will now look at the RYE_HOME to determine the location of the .rye folder. If it's not set, $HOME/.rye is used as before.

  • Rye now has a most consistent handling for virtualenv versions. If .python-version is provided, that version is used. Otherwise if requires-python is set in the pyproject.toml, that version is used instead. When a new project is created the .python-version file is written and the current latest cpython version is picked.

  • It's now possible to explicitly set the name of the project when initializing a new one.

  • Rye's init command now attempts to initialize projects with git and will automatically create a src/project_name/__init__.py file.

  • Rye can now also generate a license text when initializing projects.

  • Rye now supports negative (exclusion) dependencies. These can be used to prevent a dependency from installing, even if something else in the graph depends on it. Use rye add --exclude package-name to add such a dependency.

  • sync now accepts --no-lock to prevent updating the lock file.

  • Rye's add command now accepts a --pre parameter to include pre-release.

  • Rye's pin command now updates the pyproject.toml requires-python.

  • Rye's install command now accepts a --include-dep parameter to include scripts from one or more given dependencies.

  • Rye now honors requires-python in the add command. This means the the initial resolution will not pick a version higher than what's supported by the lower boundary.

  • When installing packages as global tools, a warning is now emitted if there were no scripts in the package. Additionally installing packages from local paths and zip files is now supported.

  • A rye self update command was added to compile and install the latest version via cargo.

  • Added more convenient ways to install from git/urls by supplying a --git or --url parameter. This will behind the scenes format a PEP 508 requirement string.

  • Added a shell command which will spawn a shell with the virtualenv activated.

  • Added a make-req command to conveniently format out PEP 508 requirement strings from parts.

  • The internal virtualenv used to manage pip-tools and other libraries now automatically updates when necessary.

  • rye toolchain register can now be used to register a local python installation as toolchain with rye.

  • rye build was added to allow building sdist and bdist_wheel distributions.

  • Rye now correctly handles whitespace in folder names.

"},{"location":"community/","title":"Community","text":"

Rye is a new project and feedback is greatly appreciated. Lots of it. Because of this there are various different ways in which you can engage with either the developer or other members of the community:

  • Discussion Forum, to discuss the project on GitHub
  • Discord, for conversations with other developers in text form
  • Issue Tracker, if you run into bugs or have suggestions

You can also reach out via Twitter or Bluesky.

"},{"location":"community/#badges","title":"Badges","text":"

Want to show that you are using Rye? Why not throw a badge into your project's README.md:

[![Rye](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/rye/main/artwork/badge.json)](https://rye-up.com)\n

... or README.rst:

.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/rye/main/artwork/badge.json\n    :target: https://rye-up.com\n    :alt: Rye\n

... or, as HTML:

<a href=\"https://rye-up.com\"><img src=\"https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/rye/main/artwork/badge.json\" alt=\"Rye\" style=\"max-width:100%;\"></a>\n

"},{"location":"philosophy/","title":"Philosophy and Vision","text":"

Rye was built to solve my problems. Here is what was on my mind when I built it:

  • Virtualenvs: while I personally do not like virtualenvs that much, they are so widespread and have reasonable tooling support, so I chose this over __pypackages__.

  • No Default Dependencies: the virtualenvs when they come up are completely void of dependencies. Not even pip or setuptools are installed into it. Rye manages the virtualenv from outside the virtualenv.

  • No Core Non Standard Stuff: Rye (with the exception of it's own tool section in the pyproject.toml) uses standardized keys. That means it uses regular requirements as you would expect. It also does not use a custom lock file format and uses uv and pip-tools behind the scenes.

  • No Pip: Rye uses pip, but it does not expose it. It manages dependencies in pyproject.toml only.

  • No System Python: I can't deal with any more linux distribution weird Python installations or whatever mess there is on macOS. I used to build my own Pythons that are the same everywhere, now I use indygreg's Python builds. Rye will automatically download and manage Python builds from there. No compiling, no divergence.

  • Project Local Shims: Rye maintains a python shim that auto discovers the current pyproject.toml and automatically operates below it. Just add the shims to your shell and you can run python and it will automatically always operate in the right project.

"},{"location":"philosophy/#what-could-be","title":"What Could Be?","text":"

There are a few shortcomings in the Python packaging world, largely as a result of lack of standardization. Here is what this project ran into over the years:

  • No Python Binary Distributions: CPython builds from python.org are completely inadequate. On some platforms you only get an .msi installer, on some you literally only get tarballs. The various Python distributions that became popular over the years are diverging greatly and cause all kinds of nonsense downstream. This is why this Project uses the indygreg standalone builds. I hope that with time someone will start distributing well maintained and reliable Python builds to replace the mess we are dealing with today.

  • No Dev Dependencies: Rye currently needs a custom section in the pyproject.toml to represent dev dependencies. There is no standard in the ecosystem for this. It really should be added.

  • No Local Dependency Overlays: There is no standard for how to represent local dependencies. Rust for this purpose has something like { path = \"../foo\" } which allows both remote and local references to co-exist and it rewrites them on publish.

  • No Exposed Pip: pip is intentionally not exposed. If you were to install something into the virtualenv, it disappears next time you sync. If you symlink rye to ~/.rye/shims/pip you can get access to pip without installing it into the virtualenv. There be dragons.

  • No Workspace Spec: for monorepos and things of that nature, the Python ecosystem would need a definition of workspaces. Today that does not exist which forces every tool to come up with it's own solutions to this problem.

  • No Basic Script Section: There should be a standard in pyproject.toml to represent scripts like rye does in rye.tools.scripts.

"},{"location":"philosophy/#the-vision","title":"The Vision","text":"

This describes of what I envision Python packaging and project management could look like in an ideal world:

"},{"location":"philosophy/#the-rust-experience","title":"The Rust Experience","text":"

Coming from a Rust environment there are two tools which work together: rustup and cargo. The first one of those is used to ensure that you have the correct Rust toolchain on your machine. Rust greatly prefers binary distributions of the language from the official website over external distributions.

cargo is the main entry point to development in Rust. It acts as the tool to trigger test runs, start the build process, shell out to the documentation building tool, linters but also things such as workspace management, dependency management and package publishing.

Crucially a very important aspect of the Rust development experience is the strong commitment to semver and the built-in support for it. This goes very deep. The resolver for instance will deduplicate matching dependencies throughout the graph. This means that if four libraries depend on libc@0.2, they will all resolve to that dependency. However if another need arises for libc@1.0, then it's possible for the dependency graph to result in both being loaded!

The ecosystem greatly depends on this. For instance when a new major release is made of a very core library, in some cases extra care is taken to unify the now incompatible versions by re-exporting core types from the newer to the older version. Thus it's for instance possible for important-lib@0.2.32 to depend on important-lib@1.0 internally so it can make the transition easier.

Additionally Rust heavily leverages lockfiles. Whenever you compile, the dependencies are locked in place and future builds reuse the same dependency versions unless you update.

Most importantly though the Rust ecosystem has embraced rustup and cargo that the vast majority of people are using these tools on a daily basis. Even developers who pick other tools like buck, are still using cargo regularly.

"},{"location":"philosophy/#going-python","title":"Going Python","text":"

Rye wants to explore if such an experience is possible with Python. I believe it can! There is quite a lot of the ecosystem that can be leveraged for this purpose but there is even more that would need to be built.

Important note: when you read \"rye\" in the context of the document it talks about what a potential tool like rye could be. It might as well be that one of the many tools that exist today, turn into that very tool that is described here.

My sentiment is that unless \"the one tool\" can emerge in the Python world, the introduction of yet another tool might be a net-negative to the ecosystem. Plenty of tools have been created over the years, and unfortunately it hasn't been able to rally the majority of the Python community behind any tool. I do however believe it is possible.

"},{"location":"philosophy/#bootstrapping-python","title":"Bootstrapping Python","text":"

I believe the right approach is that >95% of users get a Python distribution via rye and not to have rye pick up a system installed Python distribution. There are good reasons for using a system Python installation, but it should be the exception not the rule. Most importantly because a Python distribution that rye puts in place can be made to have reliable and simple rules that do not differ between systems.

A huge cause of confusion and user frustration currently comes from Linux distribution specific patches on top of Python that break tools and change behavior, particularly in the python packaging ecosystem.

Bootstrapping Python via an independent tool has other benefits as well. It for instance allows much easier cross-python version testing via tox or CI.

What needs to be done:

  • Provide widely available Python builds, with largely standardized structure retrievable from the internet. PEP 711 is a step in that direction.
"},{"location":"philosophy/#a-stronger-resolver","title":"A Stronger Resolver","text":"

Today there are a ton of different resolvers in the Python ecosystem. Pip has two, poetry has one, pdm has one, different independent Python and Rust resolvers exist on top of that. Resolvers are important, but unfortunately, there are both too many and too many issues with the existing ones. Here is what I believe a resolver needs to be able to accomplish:

  • Allow resolving across markers: most resolvers in the Python ecosystem today can only resolve for the current interpreter and platform (eg: pip, pip-tools). This means it cannot create a resolution that is equally valid for a different platform. In part this is a problem because of how environment markers in Python are defined. They allow a level of expressiveness that cannot be reflected by most tools, however a subset could be supported.

  • Multi-version resolution support: this is a bit foreshadowing, but I believe for a variety of reasons it needs to be possible for a resolver to not unify all requirements to a single version, but to support multiple independent resolutions across major versions of libraries. A future resolver should be able to permit package==2.0 and package==1.1 to both be resolved for different parts of the tree.

  • Resolver API: access to the resolver is important. For editor plugins, or custom tools it's always necessary to be able to resolve packages. For instance if you want something as trivial as \"add latest supported version of 'flask' to my pyproject.toml\" you need to be able to work with the resolver.

  • Filters: I strongly believe that a good resolver also needs a filter on top. For instance it must be possible for a developer to restrict the resolver to stay within the bounds of the target Python version and to never upgrade into a tree containing Python versions that are too new. Likewise for supply chain safety a resolver should be able to restrict itself to a set of vetted dependencies.

What needs to be done:

  • Create a reusable resolver that can be used by multiple tools in the ecosystem.
  • Make the resolver work with the proposed metadata cache
  • Expose the resolver as API for multiple tools to use.
  • Add a policy layer into the resolver that can be used to filter down the dependencies before use.
"},{"location":"philosophy/#metadata-caches","title":"Metadata Caches","text":"

Because of the rather simplistic nature of Python packages and package indexes a resolver will always be restricted by the metadata that it can reliably pull. This is particularly bad if the system needs to fall back to sdist uploads which in the worst case requires executing python code to determine the dependencies, and those dependencies might not even match on different platforms.

However this is a solvable problem with sufficient caching, and with the right design for the cache, this cache could be shared. It might even be quite interesting for PyPI to serve up \"fake\" metadata records for popular sdist only packages to help resolvers. This might go a long way in improving the quality of the developer experience.

What needs to be done:

  • Local metadata caches are added for the resolver to use
  • PyPI gains the ability to serve dependency meta data
"},{"location":"philosophy/#lockfiles","title":"Lockfiles","text":"

It's unclear if a standard can emerge for lock files given the different requirements, but a Python packaging solution needs to have support for these. There are a lot of different approaches to lockfiles today (poetry and pdm for instance have them) but it's not entirely clear to me that the way they are handled today is sufficiently pragmatic to enable a tool that is based on lockfiles to get majority adoption.

The reason in part relates the suboptimal situation with resolvers (eg: large projects can take ten minutes or longer to dependency check in poetry), on the other hand however also because of the reality of how dependencies are currently declared. For instance certain libraries will \"over\" depend on third party libraries, even if they are not needed for a developer. These pulled in dependencies however will still influence the resolver.

Most importantly a good lockfile also covers platforms other than the current developer's machine. This means that if a project supports Windows and Linux, the lockfile should be handling either dependency trees. This is what cargo accomplishes today, but cargo has a a much simpler problem to solve here because it has perfect access to package metadata which resolvers in Python do not have today. What is also problematic in Python is that certain parts of the dependency tree can be version dependent. In Rust a library A either depends on library B or it does not, but it does not depend on it conditional to a Python version.

The total expressiveness of Python dependencies is challenging. The lack of good metadata access for the resolver combined with the ability to make dependencies optional conditional to the Python version is tricky by itself. The complexity however is compounded by the fact that the resolver needs to come to a solution that can only result in a single resolved version per package.

What needs to be done:

  • Experiment with a restricted lock format that satisfies a subset of what markers provide today, that strikes a good balance.
  • Provide lockfile support as part of the resolver library.
"},{"location":"philosophy/#upper-bounds-multi-versioning","title":"Upper Bounds & Multi Versioning","text":"

Resolving Python dependencies is particularly challenging because a single solution must be found per package. A reason this works at all in the Python ecosystem is that most libraries do not set upper bounds. This means that they will be eagerly accepting future libraries even at the cost of not supporting them. That's largely possible because Python is a dynamic language and a lot of flexibility is usually possible here. However with increased utilization of type information in the Python world, and maybe with stronger desires for proper locking, it might be quite likely that upper version bounds become more common.

Once that happens however, the Python ecosystem will quite quickly run into blocking future upgrades until the entire dependency graph has moved up which creates a lot of friction. Other ecosystems have solved this problem by strictly enforcing semver semantics onto packages and by permitting multiple semver incompatible libraries to be loaded simultaneously. While usually a library is only allowed to permit on a single version of a dependency, that dependency can exist in different versions throughout the dependency tree.

In Python there is a perceived worry that this cannot be accomplished because of how site-packages, PYTHONPATH and sys.modules works. However I believe these to be solvable issues. On the one hand because .pth files can be used to completely change how the import system works, secondly because the importlib.metadata API is strong enough these days to allow a package to resolve it's own metadata. The combination of the two can be used to \"redirect\" imports in sys.modules and import statements to ensure that if a library imports a dependency of itself, it ends up with the right version.

What needs to be done:

  • Add a new metadata key to pyproject.toml that declares that a package supports multi-versioning
  • Enforce semver semantics on multi-version dependencies
  • Provide an import hook that provides multi-version imports as part of Rye
  • Relax the resolver to permit multiple solutions for multi-version dependencies
"},{"location":"philosophy/#workspaces-and-local-multi-path-references","title":"Workspaces and Local / Multi Path References","text":"

With growing development teams one of the most frustrating experiences is the inability to break up a monolithic Python module into smaller modules without having to constantly publish minor versions to a package index. The way the Rust ecosystem deals with this issue is two-fold: on the one hand Rust supports workspaces natively. Workspaces share dependencies and the resolver results. The equivalent in Python would be that a workspace shares a virtualenv across all of the projects within in. The second way in which Rust solves this problem is to permit a dependency to both support declaration of the package name, index but also local reference.

While also Rust does not permit a crate to be published to a package index with references to packages outside of the index, a separate rewrite step kicks in ahead of publish to clean out invalid dependency references. If no valid reference remains, the package will not publish.

What needs to be done:

  • requirement declarations need to be expanded to support defining the name of the index where they can be found, and optional local path references.
"},{"location":"philosophy/#every-project-in-a-virtualenv","title":"Every Project in a Virtualenv","text":"

While virtualenv is not my favorite tool, it's the closest we have to a standard. I proposed that there is always one path for a virtualenv .venv and when Rye manages it, users should not interact with it manually. It's at that point rye's responsibility to manage it, and it shall manage it as if it was a throw-away, always re-creatable scratch-pad for dependencies.

Preferably over time the structure of virtualenvs aligns between different Python versions (eg: Windows vs Linux) and the deeply nested lib/py-ver/site-packages structure is flattened out.

What needs to be done:

  • Agree on a name for where managed virtualenvs are placed (eg: .venv in the workspace root)
"},{"location":"philosophy/#dev-and-tool-dependencies","title":"Dev and Tool Dependencies","text":"

Another topic that is currently unresolved across tools in the ecosystem is how to work with dependencies that are not used in production. For instance it's quite common that a certain dependency really only matters on the developer's machine. Today pdm and some other tools have custom sections in the pyproject.toml file to mark development dependencies, but there is no agreement across tools on it.

What needs to be done:

There needs to be an agreed upon standard for all tools. See this discussion

"},{"location":"philosophy/#opinionated-defaults","title":"Opinionated Defaults","text":"

Python against PEP-8's wishes just has too many ways in which things can be laid out. There should be a much stronger push towards encouraging common standards:

What needs to be done:

  • Rye shall ship with the one true formatter
  • Rye shall ship with the one true linter
  • Rye shall always create a preferred folder structure for new projects
  • Rye shall loudly warn if package-foo does not provide a package_foo module
"},{"location":"philosophy/#existing-tools","title":"Existing Tools","text":"

Some of the existing tools in the ecosystem are close, and there is a good chance that some of these might be able to combine forces to create that one-true tool. I hope that there is enough shared interest, that we don't end up with three tools that all try to be Rye.

"},{"location":"guide/","title":"Introduction","text":"

Rye is still a very experimental tool, but this guide is here to help you get started. Before we dive into the installation and basic usage guide it's important for you to understand what Rye actually is.

Rye is a one-stop-shop tool. The idea is that as a Python developer all you need to know is Rye, because Rye is your start into the experience. As a Rye user you do not even need to install Python yourself as Rye does this for you. This means to use Rye, you just need to install Rye, the rest is done by Rye itself.

Once Rye is on your system, it can automatically install Python interpreters for you, install packages from package indexes, manage virtualenvs behind the scenes and more.

Interested? Then head over to Installation to learn about how to get Rye onto your system. Once that is done, read the Basics to learn about how Rye can be used.

"},{"location":"guide/basics/","title":"Basics","text":"

To use Rye you need to have a pyproject.toml based Python project. For this guide you can create one with rye init which will create a new folder with a new project inside:

rye init my-project\ncd my-project\n

The following structure will be created:

.\n\u251c\u2500\u2500 .git\n\u251c\u2500\u2500 .gitignore\n\u251c\u2500\u2500 .python-version\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 pyproject.toml\n\u2514\u2500\u2500 src\n    \u2514\u2500\u2500 my_project\n        \u2514\u2500\u2500 __init__.py\n

Good to Know

The init command accepts a lot of options to customize what it generates. Run rye init --help to see all the options available in the version you have installed.

A pyproject.toml is used to store metadata about your project as well as some Rye configuration. Most of Rye's commands will require a pyproject.toml to work. Note that Rye today does not support setup.py based projects. Note that when Rye initializes a project it also writes a .python-version file. This file contains the version number of the Python version that should be used for this project. It can be changed by running rye pin. For instance to tell Rye to use Python 3.10:

$ rye pin 3.10\n
"},{"location":"guide/basics/#first-sync","title":"First Sync","text":"

Once that is done, you can use rye sync to get the first synchronization. After that, Rye will have created a virtualenv in .venv and written lockfiles into requirements.lock and requirements-dev.lock.

rye sync\n

The virtualenv that Rye manages is placed in .venv next to your pyproject.toml. The first time you run this you will notice that Rye automatically downloaded and installed a compatible CPython interpreter for you. If you have already another Python installation on your system it will not be used! For more information about this behavior read about toolchains.

You can activate and work with it as normal with one notable exception: the Python installation in it does not contain pip. If you have correctly installed Rye with the shims enabled, after the sync you can run python and you will automatically be operating in that virtualenv, even if it's not enabled. You can validate this by printing out sys.prefix:

python -c \"import sys; print(sys.prefix)\"\n

It will print out the full path to the managed virtualenv.

"},{"location":"guide/basics/#adding-dependencies","title":"Adding Dependencies","text":"

Use the add command to add dependencies to your project.

rye add \"flask>=2.0\"\n

Note that after add you need to run sync again to actually install it. If you want to add packages from custom indexes, you have to configure the source first.

"},{"location":"guide/basics/#listing-dependencies","title":"Listing Dependencies","text":"

You can invoke rye list to get a dump of all installed dependencies of your project. Note that this only lists dependencies that are actually installed, so make sure to sync first.

rye list\n
"},{"location":"guide/basics/#remove-a-dependency","title":"Remove a Dependency","text":"

Use the remove command to remove a dependency from the project again.

rye remove flask\n
"},{"location":"guide/basics/#working-with-the-project","title":"Working with the Project","text":"

To run executables in the context of the virtualenv you can use the run command. For instance if you want to use black you can add and run it like this:

rye add black\nrye sync\nrye run black\n

If you want to have the commands available directly you will need to activate the virtualenv like you do normally. To activate the virtualenv, use the standard methods:

UnixWindows
. .venv/bin/activate\n
.venv\\Scripts\\activate\n

To deactivate it again run deactivate:

deactivate\n
"},{"location":"guide/basics/#inspecting-the-project","title":"Inspecting the Project","text":"

The rye show command can print out information about the project's state. By just running rye show you can see which Python version is used, where the virtualenv is located and more.

rye show\n
"},{"location":"guide/basics/#executable-projects","title":"Executable projects","text":"

To generate a project that is aimed to provide an executable script, use rye init --script:

rye init --script my-project\ncd my-project\n

The following structure will be created:

.\n\u251c\u2500\u2500 .git\n\u251c\u2500\u2500 .gitignore\n\u251c\u2500\u2500 .python-version\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 pyproject.toml\n\u2514\u2500\u2500 src\n    \u2514\u2500\u2500 my_project\n        \u2514\u2500\u2500 __init__.py\n        \u2514\u2500\u2500 __main__.py\n

The pyproject.toml will be generated with a [project.scripts] section named hello that points to the main() function of __init__.py. After you synchronized your changes, you can run the script with rye run hello.

rye sync\nrye run hello\n
"},{"location":"guide/config/","title":"Configuration","text":"

Most of Rye's configuration is contained within the pyproject.toml file. There is however also a bit of global configuration to influence how it works.

"},{"location":"guide/config/#changing-home-folder","title":"Changing Home Folder","text":"

By default Rye places all it's configuration in ~/.rye on Unix and %USERPROFILE%\\.rye on Windows. This behavior can be changed via the RYE_HOME environment variable. This is useful if you do not like the default location of where Rye places it's configuration or if you need to isolate it.

"},{"location":"guide/config/#home-folder-structure","title":"Home Folder Structure","text":"

The .rye home folder contains both user configuration as well as Rye managed state such as installed toolchains. The following files and folders are placed within the .rye folder. Note that not all are there always.

"},{"location":"guide/config/#configtoml","title":"config.toml","text":"

This is a configuration file that influences how Rye operates. Today very little configuration is available there. For the available config keys see Config File.

"},{"location":"guide/config/#self","title":"self","text":"

While Rye is written in Rust, it uses a lot of Python tools internally. These are maintained in an internal virtualenv stored in this location.

"},{"location":"guide/config/#py","title":"py","text":"

In this folder Rye stores the different toolchains. Normally those are folders containing downloaded Python distributions, but they can also be symlinks or special reference files.

"},{"location":"guide/config/#shims","title":"shims","text":"

This folder contains shim binaries. These binaries are for instance the python executable which automatically proxies to the current virtualenv or globally installed tools.

"},{"location":"guide/config/#config-file","title":"Config File","text":"

The config file config.toml in the .rye folder today only is used to manage defaults. This is a fully annotated config file:

[default]\n# This is the default value that is written into new pyproject.toml\n# files for the `project.requires-python` key\nrequires-python = \">= 3.8\"\n\n# This is the default toolchain that is used\ntoolchain = \"cpython@3.11.1\"\n\n# This is the default build system that is used\nbuild-system = \"hatchling\"\n\n# This is the default license that is used\nlicense = \"MIT\"\n\n# This sets the default author (overrides the defaults from git).  The\n# format here is \"Name <email>\".\nauthor = \"Full Name <email@address.invalid>\"\n\n# The dependency operator to use by default for dependencies.  The options are\n# '>=', '~=', and '=='.  The default currently is '>='.  This affects the behavior\n# of `rye add`.\ndependency-operator = \">=\"\n\n[proxy]\n# the proxy to use for HTTP (overridden by the http_proxy environment variable)\nhttp = \"http://127.0.0.1:4000\"\n# the proxy to use for HTTPS (overridden by the https_proxy environment variable)\nhttps = \"http://127.0.0.1:4000\"\n\n[behavior]\n# When set to true the `managed` flag is always assumed to be true.\nforce-rye-managed = false\n\n# Enables global shims when set to `true`.  This means that the installed\n# `python` shim will resolve to a Rye managed toolchain even outside of\n# virtual environments.\nglobal-python = false\n\n# When set to `true` enables experimental support of uv as a replacement\n# for pip-tools. Learn more about uv here: https://github.com/astral-sh/uv\nuse-uv = false\n\n# Enable or disable automatic `sync` after `add` and `remove`.  This defaults\n# to `true` when uv is enabled and `false` otherwise.\nautosync = true\n\n# Marks the managed .venv in a way that cloud based synchronization systems\n# like Dropbox and iCloud Files will not upload it.  This defaults to true\n# as a .venv in cloud storage typically does not make sense.  Set this to\n# `false` to disable this behavior.\nvenv-mark-sync-ignore = true\n\n# a array of tables with optional sources.  Same format as in pyproject.toml\n[[sources]]\nname = \"default\"\nurl = \"http://pypi.org/simple/\"\n
"},{"location":"guide/config/#manipulating-config","title":"Manipulating Config","text":"

new in 0.9.0

The configuration can be read and modified with rye config. The keys are in dotted notation. --get reads a key, --set, --set-int, --set-bool, or --unset modify one.

rye config --set proxy.http=http://127.0.0.1:4000\nrye config --set-bool behavior.force-rye-managed=true\nrye config --get default.requires-python\n

For more information see config.

"},{"location":"guide/config/#per-project-config","title":"Per Project Config","text":"

For the project specific pyproject.toml config see pyproject.toml.

"},{"location":"guide/deps/","title":"Dependencies","text":"

Dependencies are declared in pyproject.toml however adding them can be simplified with the rye add command. In the most simple invocation it adds a regular dependency, but it can be customized.

"},{"location":"guide/deps/#adding-basic-dependency","title":"Adding Basic Dependency","text":"

To add a regular dependency just invoke rye add with the name of the Python package:

rye add Flask\n

If you also want to define a version, use a PEP 508 requirement:

rye add \"Flask>=2.0\"\n

For extra/feature dependencies you can either use PEP 508 syntax or use --features:

rye add \"Flask[dotenv]\"\nrye add Flask --features=dotenv\n

These dependencies are stored in project.dependencies.

Note about pre-releases

By default add will not consider pre-releases. This means if you add a dependency that has .dev or similar in the version number you will not find a match. To consider them, add them with --pre:

rye add \"Flask==2.0.0rc2\" --pre\n
"},{"location":"guide/deps/#development-dependencies","title":"Development Dependencies","text":"

For dependencies that should only be installed during development pass --dev

rye add --dev black\n

These dependencies are stored in the non-standard tool.rye.dev-dependencies key.

To run tools added this way without enabling the virtualenv use rye run:

rye run black\n
"},{"location":"guide/deps/#git-local-dependencies","title":"Git / Local Dependencies","text":"

To add a local or git dependency, you can pass additional parameters like --path or --git:

rye add Flask --git=https://github.com/pallets/flask\nrye add My-Utility --path ./my-utility\n

Note that when adding such dependencies, it's necessary to also provide the name of the package. Additionally for git dependencies all kinds of extra parameters such as --tag, --rev or --branch are supported.

When working with local dependencies it's strongly encouraged to configure a workspace.

"},{"location":"guide/faq/","title":"FAQ","text":"

This section should cover some commonly asked questions. If you do not find an answer here, consider reaching out to the community.

"},{"location":"guide/faq/#how-do-i-install-pytorch","title":"How Do I Install PyTorch?","text":"

PyTorch requires setting up manual sources as it's not installed via PyPI. These sources can be set up in pyproject.toml for a simple project or globally in the config.

  • Option 1: pyproject.toml

    [[tool.rye.sources]]\nname = \"pytorch\"\nurl = \"https://download.pytorch.org/whl/cpu\"\n
  • Option 2: ~/.rye/config.toml

    [[sources]]\nname = \"pytorch\"\nurl = \"https://download.pytorch.org/whl/cpu\"\n

Afterwards you can add pytorch as you would expect:

rye add torch torchvision torchaudio\n
"},{"location":"guide/faq/#windows-developer-mode","title":"Windows Developer Mode","text":"

Rye does not require symlinks but it works significantly better with them. On Windows support for symlinks is restricted to privileged accounts. The reason for this is that Symlinks were a late addition to Windows and some applications are not developed with them in mind which can cause misbehavior or in the worst case security issues in those applications. Symlinks support however is enabled when the \"developer mode\" is activated on modern Windows versions.

Enabling \"developer mode\" has changed in later version of Windows. For older versions:

  1. Press Win+I to open the settings
  2. In the settings dialog click on \"Privacy & security\"
  3. In the \"Security\" section click on \"For developers\"
  4. Enable the toggle \"Developer Mode\"
  5. In the \"Use developer features\" dialog confirm by clicking \"Yes\".

In more modern versions:

  1. Press Win+I to open the settings
  2. In the settings dialog click on \"System\"
  3. In the \"System\" section click on \"For developers\"
  4. Enable the toggle \"Developer Mode\"
  5. In the \"Use developer features\" dialog confirm by clicking \"Yes\".
What happens if I don't enable it?

Enabling symlinks is not strictly required as Rye automatically falls back to hardlinks and junction points. However not having symlinks enabled will ultimately result in a worse user experience for the following reasons:

  • Custom toolchain registration uses proxy files rather than actual symlinks which means that the executables in the .rye\\py path are non executable.
  • All shims will be installed as hardlinks. This can cause issues when upgrading Rye while Python is in use. These hardlinks will also continue to point to older Rye executables creating more hard drive usage.
  • Virtualenvs will be created with copies rather than symlinks.
  • Junction points are used where symlinks to directories are otherwise used. Some tools might accidentally not detect junction points which can cause deletion of virtualenvs to accidentally also delete or destroy the toolchain behind it.
"},{"location":"guide/faq/#missing-shared-libraries-on-linux","title":"Missing Shared Libraries on Linux","text":"

The Python builds that Rye uses require a Linux installation compatible to the Linux Standard Base Core Specification (LSB). Unfortunately not all Linux distributions are strictly adhering to that specification out of the box. In particularly the library libcrypt.so.1 is commonly not installed on certain Linux distributions but the _crypt standard library module depends on it. Depending on the Linux distributions you need to run different commands to resolve this:

  • archlinux: pacman -S libxcrypt-compat
  • CentOS/RedHat: dnf install libxcrypt-compat

There have also been reports of an error being generated at installation time despite libcrypt.so.1 being installed when a different ldd (eg: Homebrew) shadows the system one. In that case try the installation again after giving the default one higher priority in the `PATH:

export PATH=\"/usr/bin:$PATH\"\ncurl -sSf https://rye-up.com/get | bash\n
"},{"location":"guide/faq/#references-to-build-time-paths","title":"References to Build-Time Paths","text":"

The prefers using standalone Python builds. As Python historically is not much accommodating to portable builds there are various limitations still with this approach. One of them is that built Python distributions capture some absolute paths and other build-time configuration. These file paths are then often used by build tools to invoke C compilers. For instance you might run into a compiler error like error: stdio.h: No such file or directory when building C extensions. There is no known solution to this problem today other than registering a non portable toolchain.

This issue is inherited from python-build-standalone and more information can be found in the documentation: References to Build-Time Paths. There is also an open Rye issue for it: Issue #621.

"},{"location":"guide/faq/#tkinter-support","title":"TKinter Support","text":"

TKinter uses TCL behind the scenes. Unfortunately this also means that some runtime support is required. This runtime support is provided by the portable Python builds, however the way TCL is initialized on macOS and Linux won't find these files in virtualenvs. Newer versions of Rye will automatically export the TCL_LIBRARY and TK_LIBRARY environment variables for you in a manner very similar to this:

import os\nimport sys\nos.environ[\"TCL_LIBRARY\"] = sys.base_prefix + \"/lib/tcl8.6\"\nos.environ[\"TK_LIBRARY\"] = sys.base_prefix + \"/lib/tk8.6\"\n
"},{"location":"guide/faq/#python-interactive-prompt-input-messed-up","title":"Python Interactive Prompt Input Messed Up","text":"

The Python builds that Rye uses are compiled against libedit rather than readline for licensing reasons. You might run into unicode issues on input as a result of this due to limitations in libedit. In some cases though you might also discover that the backspace key does not work or arrow keys don't work as expected. This can be because the terminfo database cannot be found.

For solutions to this issue, read the behavior quirks guide in the Standalone Python Builds documentation for solutions.

"},{"location":"guide/faq/#can-i-use-rye-alongside-other-python-installations","title":"Can I use Rye Alongside Other Python Installations?","text":"

Rye given it's experimental nature does not want to disrupt already existing Python workflows. As such using it alongside other Python installations is intentionally supported. Even if the Rye shims come first on the PATH, Rye will automatically resolve to a different Python installation on the search path when invoked in a folder that contains a non Rye managed project.

As such the answer is a clear yes!

"},{"location":"guide/faq/#muslalpine-support","title":"Musl/Alpine Support","text":"

When bootstrapping it can happen that you are running into a confusing error like \"No such file or directory (os error 2)\". This can happen on MUSL based Linux systems like Alpine. The reason for this is that Rye downloads distribution independent Python interpreters which are not compatible with Linux systems that do not use glibc. The solution today is to install Python via other means and to install Rye with a custom RYE_TOOLCHAIN. For more information see Customized Installation

"},{"location":"guide/faq/#wheels-appear-to-be-missing-files","title":"Wheels Appear to be Missing Files","text":"

You might be encountering missing files in wheels when running rye build and you are using hatchling. The reason for this is that rye build uses \"build\" behind the scenes to build wheels. There are two build modes and in some cases the wheel is first built from an sdist. So if your sdists does not include the necessary data files, the resulting wheel will also be incorrect.

This can be corrected by adding the files to the include in the hatch config for sdists. For instance the following lines added to pyproject.toml will add the data files in my_package and all the tests to the sdist from which the wheel is built:

[tool.hatch.build.targets.sdist]\ninclude = [\"src/my_package\", \"tests\"]\n
"},{"location":"guide/faq/#can-i-relocate-virtualenvs","title":"Can I Relocate Virtualenvs?","text":"

Rye very intentionally places the virtualenv (.venv) in the root folder of the workspace. Relocations of virtualenvs is not supported. This is a very intentional decision so that tools do not need to deal with various complex alternatives and can rely on a simple algorithm to locate it. This is a form of convention over configuration and can also assist editor integrations.

There are some known downsides of this. For instance if you are placing your projects in Dropbox, it would cause this folder to synchronize. As a way to combat this, Rye will automatically mark the virtualenv with the necessary flags to disable cloud sync of known supported cloud synchronization systems.

For override this behavior you can set the behavior.venv-mark-sync-ignore configuration key to false.

"},{"location":"guide/faq/#why-does-rye-contain-trojan-bearfoos","title":"Why Does Rye Contain Trojan \"Bearfoos\"?","text":"

Unfortunately Windows likes to complain that Rye contains the trojan \"Win32/Bearfoos.A!ml\". This seems to be something that happens to a few programs written in Rust every once in a while because the compiler spits out some bytes that have been associated with Trojans written in Rust.

It can be ignored. For more information see the discussion Windows Bearfoos virus associated with rye.

"},{"location":"guide/installation/","title":"Installation","text":"

Rye is built in Rust. It can either be manually compiled and installed or it can be installed from a binary distribution. It has support for Linux, macOS and Windows.

"},{"location":"guide/installation/#installing-rye","title":"Installing Rye","text":"

Rye is installed per-user and self manages itself. It will install itself into a folder in your home directory and manage itself there.

LinuxmacOSWindowsCompile Yourself

To install you can run a curl command which will install the right binary for your operating system and CPU architecture and install it:

curl -sSf https://rye-up.com/get | bash\n

Alternatively if you don't trust this approach, you can download the latest release binary. On first run it will install itself.

  • rye-x86_64-linux.gz for 64bit Intel computers
  • rye-aarch64-linux.gz for 64bit ARM computers
gunzip rye-x86_64-linux.gz\nchmod +x ./rye-x86_64-linux\n./rye-x86_64-linux\n

To install you can run a curl command which will install the right binary for your operating system and CPU architecture and install it:

curl -sSf https://rye-up.com/get | bash\n

Alternatively if you don't trust this approach, you can download the latest release binary. On first run it will install itself.

  • rye-aarch64-macos.gz for M1/M2 Macs
  • rye-x86_64-macos.gz for Intel Macs
gunzip rye-aarch64-macos.gz\nchmod +x ./rye-aarch64-macos\n./rye-aarch64-macos\n

To install Rye on windows download the latest release and run the binary. Upon first run it will install itself. Please note that it's strongly recommended to have \"Developer Mode\" activated when using Rye and before starting the installation. Learn more.

  • rye-x86_64-windows.exe for 64bit Intel Windows
  • rye-x86-windows.exe for 32bit Intel Windows

Note

Rye does not yet use signed binaries which means that you will need to allow the execution of the downloaded executable. If there is no obvious way to do so, click on \"More info\" on the error message that shows up and then on \"Run anyway\".

Additionally sometimes a Trojan warning about \"Bearfoos\" is shown. This is a false positive. For more information see the discussion Windows Bearfoos virus associated with rye.

You need to have Rust and Cargo installed. If you don't have, you can use rustup to get them onto your machine.

Afterwards you can install Rye via cargo:

cargo install --git https://github.com/astral-sh/rye rye\n

Rye will automatically download suitable Python toolchains as needed. For more information about this read about toolchains. To install a specific version download a binary directly from GitHub.

"},{"location":"guide/installation/#customized-installation","title":"Customized Installation","text":"

On some platforms there is some limited support for customizing the installation experience. This for instance can be necessary on certain Linux environments such as Alpine where the Rye provided Python interpreter is not supported.

LinuxmacOSWindows

The install script that is piped to bash can be customized with some environment variables:

RYE_VERSION

Defaults to latest. Can be set to an explicit version to install a specific one.

RYE_INSTALL_OPTION

Can optionally be set to \"--yes\" to skip all prompts.

RYE_TOOLCHAIN

Optionally this environment variable can be set to point to a Python interpreter that should be used as the internal interpreter. If not provided a suitable interpreter is automatically downloaded.

At present only CPython 3.9 to 3.12 are supported.

RYE_TOOLCHAIN_VERSION

For Rye 0.22 and later a specific Python version can be picked rather than the default. This affects the internal toolchain version only. It's useful for Docker builds where you can set the internal toolchain to the same as your project to only fetch a single Python.

At present only CPython 3.9 to 3.12 are supported.

This for instance installs a specific version of Rye without asking questions:

curl -sSf https://rye-up.com/get | RYE_VERSION=\"0.4.0\" RYE_INSTALL_OPTION=\"--yes\" bash\n

The install script that is piped to bash can be customized with some environment variables:

RYE_VERSION

Defaults to latest. Can be set to an explicit version to install a specific one.

RYE_INSTALL_OPTION

Can optionally be set to \"--yes\" to skip all prompts.

RYE_TOOLCHAIN

Optionally this environment variable can be set to point to a Python interpreter that should be used as the internal interpreter. If not provided a suitable interpreter is automatically downloaded.

At present only CPython 3.9 to 3.12 are supported.

RYE_TOOLCHAIN_VERSION

For Rye 0.22 and later a specific Python version can be picked rather than the default. This affects the internal toolchain version only. It's useful for Docker builds where you can set the internal toolchain to the same as your project to only fetch a single Python.

At present only CPython 3.9 to 3.12 are supported.

This for instance installs a specific version of Rye without asking questions:

curl -sSf https://rye-up.com/get | RYE_VERSION=\"0.4.0\" RYE_INSTALL_OPTION=\"--yes\" bash\n

The Windows installer has limited support for customizations via environment variables. To set these you need to run the installer from cmd.exe.

RYE_TOOLCHAIN

Optionally this environment variable can be set to point to a Python interpreter that should be used as the internal interpreter. If not provided a suitable interpreter is automatically downloaded.

At present only CPython 3.9 to 3.12 are supported.

RYE_TOOLCHAIN_VERSION

For Rye 0.22 and later a specific Python version can be picked rather than the default. This affects the internal toolchain version only. It's useful for Docker builds where you can set the internal toolchain to the same as your project to only fetch a single Python.

At present only CPython 3.9 to 3.12 are supported.

This for instance installs Rye with a specific toolchain:

set RYE_TOOLCHAIN=%USERPROFILE%\\AppData\\Local\\Programs\\Python\\Python310\\python.exe\nrye-x86_64-windows.exe\n
"},{"location":"guide/installation/#add-shims-to-path","title":"Add Shims to Path","text":"

Once rye is installed you need to add the shims folder into your PATH. This folder is a folder that contains \"shims\" which are executables that Rye manages for you as well as the rye executable itself. For instance any Python installation managed by Rye will be available via a shim placed there.

On macOS or Linux you can accomplish this by adding it to your .profile file or similar. This step is technically optional but required if you want to be able to just type python or rye into the shell to pick up the current virtualenv's Python interpreter. The installer will offer to do this for you automatically. If you opt-out, or you run a custom shell you will need to do this manually.

BashZSHFishNushellUnix ShellsWindows

Rye ships an env file which should be sourced to update PATH automatically.

echo 'source \"$HOME/.rye/env\"' >> ~/.profile\n

In some setups .profile is not sourced, in which case you can add it to your .bashrc:

echo 'source \"$HOME/.rye/env\"' >> ~/.bashrc\n

Rye ships an env file which should be sourced to update PATH automatically.

echo 'source \"$HOME/.rye/env\"' >> ~/.zprofile\n

In some setups .zprofile is not sourced, in which case you can add it to your .zshrc:

echo 'source \"$HOME/.rye/env\"' >> ~/.zshrc\n

Since fish does not support env files, you need to add the shims directly. This can be accomplished by running this command once:

set -Ua fish_user_paths \"$HOME/.rye/shims\"\n

Since nushell does not support env files, you need to add the shims directly. This can be accomplished by adding this to your env.nu file:

$env.PATH = ($env.PATH | split row (char esep) | append \"~/.rye/shims\")\n

Rye ships an env file which should be sourced to update PATH automatically.

echo '. \"$HOME/.rye/env\"' >> ~/.profile\n

The windows installer normally will automatically register the rye path in the PATH environment variable. If this does not work you will need to manually perform the following steps:

  1. Press Win+R, enter sysdm.cpl and hit Enter.
  2. In the \"System Properties\" dialog, click the \"Advanced\" tab.
  3. Click on \"Environment Variables\".
  4. In the top list, double click on the Path variable.
  5. In the \"Edit environment variable\" dialog click on \"New\".
  6. Enter %USERPROFILE%\\.rye\\shims and hit Enter.
  7. Click repeatedly on \"Move Up\" until the newly added item is at the top.
  8. Click on \"OK\" and close the dialog.

Note that you might need to restart your login session for this to take effect.

There is a quite a bit to shims and their behavior. Make sure to read up on shims to learn more.

"},{"location":"guide/installation/#shell-completion","title":"Shell Completion","text":"

Rye supports generating completion scripts for Bash, Zsh, Fish or Powershell. Here are some common locations for each shell:

BashZshFishPowershell
mkdir -p ~/.local/share/bash-completion/completions\nrye self completion > ~/.local/share/bash-completion/completions/rye.bash\n
# Make sure ~/.zfunc is added to fpath, before compinit.\nrye self completion -s zsh > ~/.zfunc/_rye\n

Oh-My-Zsh:

mkdir $ZSH_CUSTOM/plugins/rye\nrye self completion -s zsh > $ZSH_CUSTOM/plugins/rye/_rye\n

Then make sure rye plugin is enabled in ~/.zshrc

rye self completion -s fish > ~/.config/fish/completions/rye.fish\n
# Create a directory to store completion scripts\nmkdir $PROFILE\\..\\Completions\necho @'\nGet-ChildItem \"$PROFILE\\..\\Completions\\\" | ForEach-Object {\n    . $_.FullName\n}\n'@ | Out-File -Append -Encoding utf8 $PROFILE\n# Generate script\nSet-ExecutionPolicy Unrestricted -Scope CurrentUser\nrye self completion -s powershell | Out-File -Encoding utf8 $PROFILE\\..\\Completions\\rye_completion.ps1\n
"},{"location":"guide/installation/#updating-rye","title":"Updating Rye","text":"

To update rye to the latest version you can use rye itself:

rye self update\n
"},{"location":"guide/installation/#uninstalling","title":"Uninstalling","text":"

If you don't want to use Rye any more, you can ask it to uninstall it again:

rye self uninstall\n

Additionally you should delete the remaining .rye folder from your home directory and remove .rye/shims from the PATH again (usually by removing the code that sources the env file from the installation step). Rye itself does not place any data in other locations. Note though that virtual environments created by rye will no longer function after Rye was uninstalled.

"},{"location":"guide/installation/#preventing-auto-installation","title":"Preventing Auto Installation","text":"

Rye when launched will normally perform an auto installation. This can be annoying in certain development situations. This can be prevented by exporting the RYE_NO_AUTO_INSTALL environment variable. It needs to be set to 1 to disable the feature.

LinuxmacOSWindows
export RYE_NO_AUTO_INSTALL=1\n
export RYE_NO_AUTO_INSTALL=1\n
set RYE_NO_AUTO_INSTALL=1\n
"},{"location":"guide/publish/","title":"Building and Publishing","text":"

Rye currently uses build to build the package and uses twine to publish it.

"},{"location":"guide/publish/#build","title":"Build","text":"

By default, rye will build both the sdist and wheel targets in the dist directory. The command for this is called build.

rye build\n

You can use the --sdist or --wheel flag to build the specific target, or specify the output directory with --out.

rye build --wheel --out target\n

If you want to clean the build directory before building, run:

rye build --clean\n
"},{"location":"guide/publish/#publish","title":"Publish","text":"

Rye will publish the distribution files under the dist directory to PyPI by default.

rye publish\n

You might be asked to input your access token and some other info if needed.

No access token found, generate one at: https://pypi.org/manage/account/token/\nAccess token:\n

You can also specify the distribution files to be published:

rye publish dist/example-0.1.0.tar.gz\n
"},{"location":"guide/publish/#-repository","title":"--repository","text":"

Rye supports publishing the package to a different repository by using the --repository and --repository-url flags. For example, to publish to the test PyPI repository:

rye publish --repository testpypi --repository-url https://test.pypi.org/legacy/\n
"},{"location":"guide/publish/#-yes","title":"--yes","text":"

You can optionally set the --yes flag to skip the confirmation prompt. This can be useful for CI/CD pipelines.

rye publish --token <your_token> --yes\n

Rye will store your repository info in $HOME/.rye/credentials for future use.

"},{"location":"guide/publish/#-skip-existing","title":"--skip-existing","text":"

You can use --skip-existing to skip any distribution files that have already been published to the repository. Note that some repositories may not support this feature.

"},{"location":"guide/pyproject/","title":"Python Project (pyproject.toml)","text":"

Rye tries to avoid a lot of proprietary configuration in the pyproject.toml file but a bit is necessary. Here are the most important keys that Rye expects:

"},{"location":"guide/pyproject/#projectdependencies","title":"project.dependencies","text":"

This key is used to manage dependencies. They work exactly like you expect from a regular pyproject.toml file and in fact Rye changes nothing about this. However Rye is capable of modifying these entries with the rye add and rye remove commands.

[project]\ndependencies = [\n\"mkdocs~=1.4.3\",\n\"mkdocs-material~=9.1.12\",\n\"pymdown-extensions~=9.11\",\n]\n
"},{"location":"guide/pyproject/#projectscripts","title":"project.scripts","text":"

This key specifies the scripts that are to be generated and installed into the virtual environment during sync. These scripts will invoke the configured entry point.

[project.scripts]\nmy-hello-script = 'hello:main'\n
This configuration will generate a script my-hello-script that will call the main function of the hello module.

Scripts can be installed using rye sync and run using rye run:

$ rye sync\n$ rye run my-hello-script\nHello from hello!\n
"},{"location":"guide/pyproject/#toolryedev-dependencies","title":"tool.rye.dev-dependencies","text":"

This works similar to project.dependencies but holds development only dependencies. These can be added here automatically via rye add --dev.

[tool.rye]\ndev-dependencies = [\"black~=23.3.0\"]\n

Dev dependencies are installed automatically unless --no-dev is passed to sync.

"},{"location":"guide/pyproject/#toolryeexcluded-dependencies","title":"tool.rye.excluded-dependencies","text":"

This is a special key that contains dependencies which are never installed, even if they are pulled in as indirect dependencies. These are added here automatically with rye add --excluded.

[tool.rye]\nexcluded-dependencies = [\"cffi\"]\n
"},{"location":"guide/pyproject/#toolryelock-with-sources","title":"tool.rye.lock-with-sources","text":"

new in 0.18.0

When this flag is enabled all lock and sync operations in the project or workspace operate as if --with-sources is passed. This means that all lock files contain the full source references. Note that this can create lock files that contain credentials if the sources have credentials included in the URL.

[tool.rye]\nlock-with-sources = true\n
"},{"location":"guide/pyproject/#toolryemanaged","title":"tool.rye.managed","text":"

new in 0.3.0

This key tells rye that this project is supposed to be managed by Rye. This key primarily affects some automatic creation of virtualenvs. For instance Rye will not try to initialize a virtualenv when using shims without this flag. It can be forced enabled in the global config.

[tool.rye]\nmanaged = true\n
"},{"location":"guide/pyproject/#toolryevirtual","title":"tool.rye.virtual","text":"

new in 0.20.0

If this key is set to true the project is declared as a virtual project. This is a special mode in which the package itself is not installed, but only the dependencies are. This is for instance useful if you are not creating a Python project, but you are depending on Python software. As an example you can use this to install software written in Python. This key is set to true when rye init is invoked with the --virtual flag.

[tool.rye]\nvirtual = true\n

For more information consult the Virtual Project Guide.

"},{"location":"guide/pyproject/#toolryesources","title":"tool.rye.sources","text":"

This is an array of tables with sources that should be used for locating dependencies. This lets you use indexes other than PyPI. These sources can also be configured in the main config.toml config file with the same syntax.

[[tool.rye.sources]]\nname = \"default\"\nurl = \"http://pypi.org/simple/\"\n

For more information about configuring sources see Dependency Sources.

"},{"location":"guide/pyproject/#toolryescripts","title":"tool.rye.scripts","text":"

This key can be used to register custom scripts that are exposed via rye run. Each key is a script, and each value is the configuration for that script. Normally the value is an object with different keys with the most important key being cmd which holds the command to execute. However if only cmd is set, then the object is optional. cmd itself can either be set to a string or an array of arguments.

[tool.rye.scripts]\n# These three options are equivalent:\ndevserver = \"flask run --app ./hello.py --debug\"\ndevserver-alt = [\"flask\", \"run\", \"--app\", \"./hello.py\", \"--debug\"]\ndevserver-explicit = { cmd = \"flask run --app ./hello.py --debug\" }\n

The following keys are possible for a script:

"},{"location":"guide/pyproject/#cmd","title":"cmd","text":"

The command to execute. This is either a string or an array of arguments. In either case shell specific interpolation is unavailable. The command will invoke one of the tools in the virtualenv if it's available there.

[tool.rye.scripts]\ndevserver = { cmd = \"flask run --app ./hello.py --debug\" }\nhttp = { cmd = [\"python\", \"-mhttp.server\", \"8000\"] }\n
"},{"location":"guide/pyproject/#env","title":"env","text":"

This key can be used to provide environment variables with a script:

[tool.rye.scripts]\ndevserver = { cmd = \"flask run --debug\", env = { FLASK_APP = \"./hello.py\" } }\n
"},{"location":"guide/pyproject/#chain","title":"chain","text":"

This is a special key that can be set instead of cmd to make a command invoke multiple other commands. Each command will be executed one after another. If any of the commands fails, the rest of the commands won't be executed and the chain fails.

[tool.rye.scripts]\nlint = { chain = [\"lint:black\", \"lint:flake8\" ] }\n\"lint:black\" = \"black --check src\"\n\"lint:flake8\" = \"flake8 src\"\n
"},{"location":"guide/pyproject/#call","title":"call","text":"

This is a special key that can be set instead of cmd to make a command invoke python functions or modules. The format is one of the three following formats:

  • <module_name>: equivalent to python -m <module_name>
  • <module_name>:<function_name>: runs <function_name> from <module_name> and exits with the return value
  • <module_name>:<function_name>(<args>): passes specific arguments to the function

Extra arguments provided on the command line are passed in sys.argv.

[tool.rye.scripts]\nserve = { call = \"http.server\" }\nhelp = { call = \"builtins:help\" }\nhello-world = { call = \"builtins:print('Hello World!')\" }\n
"},{"location":"guide/pyproject/#toolryeworkspace","title":"tool.rye.workspace","text":"

When a table with that key is stored, then a project is declared to be a workspace root. By default all Python projects discovered in sub folders will then become members of this workspace and share a virtualenv. Optionally the members key (an array) can be used to restrict these members. In that list globs can be used. The root project itself is always a member.

[tool.rye.workspace]\nmembers = [\"mylib-*\"]\n

For more information consult the Workspaces Guide.

"},{"location":"guide/rust/","title":"Rust Modules","text":"

Rye recommends using maturin to develop Rust Python extension modules. This process is largely automated and new projects can be created with rye init.

"},{"location":"guide/rust/#new-project","title":"New Project","text":"
rye init my-project --build-system maturin\ncd my-project\n

The following structure will be created:

.\n\u251c\u2500\u2500 .git\n\u251c\u2500\u2500 .gitignore\n\u251c\u2500\u2500 .python-version\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 pyproject.toml\n\u251c\u2500\u2500 Cargo.toml\n\u251c\u2500\u2500 python\n    \u2514\u2500\u2500 my_project\n        \u2514\u2500\u2500 __init__.py\n\u2514\u2500\u2500 src\n    \u2514\u2500\u2500 lib.rs\n
"},{"location":"guide/rust/#iterating","title":"Iterating","text":"

When you use maturin as a build system then rye sync will automatically build the rust extension module into your venv. Likewise rye build will use maturin to trigger a wheel build. For faster iteration it's recommended to use maturin directly.

If you want to use other maturin commands such as maturin develop you can install it as a global tool:

rye install maturin\n

Note that maturin develop requires pip to be installed into the virtualenv. Before you can use it you need to add it:

rye add --dev pip\nrye sync\n

Rye recommends mixed python/rust modules. In that case you can save some valuable iteration time by running maturin develop --skip-install:

maturin develop --skip-install\n
"},{"location":"guide/shims/","title":"Shims","text":"

After installation Rye places two shims on your PATH: python and python3. These shims have specific behavior that changes depending on if they are used within a Rye managed project or outside.

Inside a Rye managed project they resolve to the Python interpreter of the virtualenv. This means that even if you do not enable the virtualenv, you can just run python in a shell, and it will automatically operate in the right environment.

Outside a Rye managed project it typically resolves to your system Python, though you can also opt to have it resolve to a Rye managed Python installation for you. This is done so that it's not disruptive to your existing workflows which might depend on the System python installation.

"},{"location":"guide/shims/#global-shims","title":"Global Shims","text":"

new in 0.9.0

To enable global shims, you need to enable the global-python flag in the config.toml file:

rye config --set-bool behavior.global-python=true\n

Afterwards if you run python outside of a Rye managed project it will spawn a Python interpreter that is shipped with Rye. It will honor the closest .python-version file for you. Additionally you can also explicitly request a specific Python version by adding +VERSION after the python command. For instance this runs a script with Python 3.8:

python +3.8 my-script.py\n

Note

Selecting a specific Python version this way only works outside of Rye managed projects. Within Rye managed projects, the version needs to be explicitly selected via .python-version or with the requires-python key in pyproject.toml.

"},{"location":"guide/sources/","title":"Dependency Sources","text":"

new in 0.2.0

Normally Rye loads packages from PyPI only. However it is possible to instruct it to load packages from other indexes as well.

"},{"location":"guide/sources/#adding-a-source","title":"Adding a Source","text":"

An index can be added to a project or workspace (via pyproject.toml) or into the global config. Rye will always consult both files where the pyproject.toml file wins over the global config.

Each source needs to have a unique name. The default source is always called default and out of the box points to PyPI.

Global SourceProject Source

Add this to ~/.rye/config.toml:

[[sources]]\nname = \"company-internal\"\nurl = \"https://company.internal/simple/\"\n

Add this to pyproject.toml:

[[tool.rye.sources]]\nname = \"company-internal\"\nurl = \"https://company.internal/simple/\"\n

changed in 0.4.0

Sources in the global config are also considered for tool installations.

"},{"location":"guide/sources/#index-types","title":"Index Types","text":"

Rye supports different types of sources and also allows overriding the default PyPI index. If you give another source the name default, PyPI will no longer be used for resolution.

Regular IndexFind LinksDefault Index
[[sources]]\nname = \"company-internal\"\nurl = \"https://company.internal/simple/\"\ntype = \"index\"  # this is implied\n
[[sources]]\nname = \"company-internal\"\nurl = \"https://company.internal/\"\ntype = \"find-links\"\n
[[sources]]\nname = \"default\"\nurl = \"https://company.internal/simple/\"\n

Warning

Please take note that the default index cannot be of type find-links.

"},{"location":"guide/sources/#source-types","title":"Source Types","text":"

The two sources types (index vs find-links) are determined by the underlying pip infrastructure:

"},{"location":"guide/sources/#index","title":"index","text":"

This is a PEP 503 type index as provided by tools such as PyPI or devpi. It corresponds to the arguments --index-url or --extra-index-url in pip.

"},{"location":"guide/sources/#find-links","title":"find-links","text":"

This is a source that can be of a variety of types and has to point to a file path or hosted HTML page linking to packages. It corresponds to the --find-links argument. The format of the HTML page is somewhat underspecified but generally all HTML links pointing to .tar.gz or .whl files are considered.

"},{"location":"guide/sources/#index-authentication","title":"Index Authentication","text":"

HTTP basic auth is supported for index authentication. It can be supplied in two ways. username and password can be directly embedded in the config, or they can be supplied with environment variables.

Configured CredentialsEnvironment Variables
[[sources]]\nname = \"company-internal\"\nurl = \"https://company.internal/simple/\"\nusername = \"username\"\npassword = \"super secret\"\n
[[sources]]\nname = \"company-internal\"\nurl = \"https://${INDEX_USERNAME}:${INDEX_PASSWORD}@company.internal/simple/\"\n
"},{"location":"guide/sources/#ssltls-verification","title":"SSL/TLS Verification","text":"

By default a source needs to be SSL/TLS protected. If not, rye will refuse to honor the source. You can override this by setting verify-ssl to false:

[[sources]]\nname = \"company-internal\"\nurl = \"http://company.internal/simple/\"\nverify-ssl = false\n
"},{"location":"guide/sync/","title":"Syncing and Locking","text":"

Rye supports two systems to manage dependencies: uv and pip-tools. It currently defaults to pip-tools but will offer you the option to use uv instead. uv will become the default choice once it stabilzes as it offers significantly better performance.

In order to download dependencies rye creates two \"lockfiles\" (called requirements.lock and requirements-dev.lock). These are not real lockfiles but they fulfill a similar purpose until a better solution has been implemented.

Whenever rye sync is called, it will update lockfiles as well as the virtualenv. If you only want to update the lockfiles, then rye lock can be used.

"},{"location":"guide/sync/#lock","title":"Lock","text":"

When locking, some options can be provided to change the locking behavior. These flags are also all available on rye sync.

"},{"location":"guide/sync/#-update-update-all","title":"--update / --update-all","text":"

Updates a specific or all requirements to the latest and greatest version. Without this flag a dependency will only be updated if necessary.

rye lock --update-all\n
"},{"location":"guide/sync/#-features-all-features","title":"--features / --all-features","text":"

Python packages can have extra dependencies. By default the local package that is installed will only be installed with the default features. If for instance you have an extra dependency this will only be installed if the feature is enabled.

rye add --optional=web flask\nrye lock --features=web\n

When working with workspaces, the package name needs to be prefixed with a slash:

rye lock --features=package-name/feature-name\n

The --features parameter can be passed multiple times and features can also be comma separated. To turn on all features, the --all-features parameter can be used.

rye lock --all-features\n
"},{"location":"guide/sync/#-pre","title":"--pre","text":"

By default updates and version resolution will not consider pre-releases of packages. If you do want to include those, pass --pre

rye lock Flask --pre\n
"},{"location":"guide/sync/#-with-sources","title":"--with-sources","text":"

new in 0.18.0

By default (unless the tool.rye.lock-with-sources config key is set to true in the pyproject.toml) lock files are not generated with source references. This means that if custom sources are used the lock file cannot be installed via pip unless also --find-links and other parameters are manually passed. This can be particularly useful when the lock file is used for docker image builds.

When this flag is passed then the lock file is generated with references to --index-url, --extra-index-url or --find-links.

rye lock --with-sources\n
"},{"location":"guide/sync/#sync","title":"Sync","text":"

Syncing takes the same parameters as lock and then some. Sync will usually first do what lock does and then use the lockfiles to update the virtualenv.

"},{"location":"guide/sync/#-no-lock","title":"--no-lock","text":"

To prevent the lock step from automatically running, pass --no-lock.

rye sync --no-lock\n
"},{"location":"guide/sync/#-no-dev","title":"--no-dev","text":"

Only sync based on the production lockfile (requirements.lock) instead of the development lockfile (requirements-dev.lock).

rye sync --no-dev\n
"},{"location":"guide/sync/#limitations","title":"Limitations","text":"

Lockfiles depend on the platform they were generated on. This is a known limitation in pip-tools.

For example, if your project relies on platform-specific packages and you generate lockfiles on Windows, these lockfiles will include Windows-specific projects. Consequently, they won't be compatible with other platforms like Linux or macOS.

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

Rye supports global tool installations. This for instance allows you to install tools like black or ruff globally.

"},{"location":"guide/tools/#installing-tools","title":"Installing Tools","text":"

Use the rye tools install (aliased to rye install) command to install a tool globally with a shim:

rye install ruff\n

Afterwards the tool is installed into ~/.rye/tools/ruff and the necessary shims are placed in ~/.rye/shims.

changed in 0.4.0

The install command now considers custom sources configured in the config.toml file. For more information see Dependency Sources.

"},{"location":"guide/tools/#extra-requirements","title":"Extra Requirements","text":"

Some tools do not declare all of their dependencies since they might be optional. In some cases these can be declared by passing extra features to the installer:

rye install black --features colorama\n

If dependencies are not at all specified, then they can be provided with --extra-requirement. This is particularly sometimes necessary if the tool uses pkg_resources (part of setuptools) but forgets to declare that dependency:

rye install gradio --extra-requirement setuptools\n
"},{"location":"guide/tools/#listing-tools","title":"Listing Tools","text":"

If you want to see which tools are installed, you can use rye tools list:

rye tools list\n
black\n  black\n  blackd\nruff\n  ruff\n

To also see which scripts those tools provide, also pass --include-scripts

rye tools list --include-scripts\n
"},{"location":"guide/tools/#uninstalling-tools","title":"Uninstalling Tools","text":"

To uninstall a tool again, use rye tools uninstall (aliased to rye uninstall):

rye uninstall black\n
"},{"location":"guide/virtual/","title":"Virtual Projects","text":"

new in 0.20.0

Virtual projects are projects which are themselves not installable Python packages, but that will sync their dependencies. They are declared like a normal python package in a pyproject.toml, but they do not create a package. Instead the tool.rye.virtual key is set to true.

For instance this is useful if you want to use a program like mkdocs without declaring a package yourself:

rye init --virtual\nrye add mkdocs\nrye sync\nrye run mkdocs\n

This will create a pyproject.toml but does not actually declare any python code itself. Yet when synching you will end up with mkdocs in your project.

"},{"location":"guide/virtual/#behavior-changes","title":"Behavior Changes","text":"

When synching the project itself is never installed into the virtualenv as it's not considered to be a valid package. Likewise you cannot publish virtual packages to PyPI or another index.

"},{"location":"guide/virtual/#limitations","title":"Limitations","text":"

Virtual projects can not have optional dependencies. These even if declared are not installed.

"},{"location":"guide/virtual/#workspaces","title":"Workspaces","text":"

If a workspace does not have a toplevel package it's recommended that it's declared as virtual.

"},{"location":"guide/workspaces/","title":"Workspaces","text":"

Workspaces are a feature that allows you to work with multiple packages that have dependencies to each other. A workspace is declared by setting the tool.rye.workspace key a pyproject.toml. Afterwards all projects within that workspace share a singular virtualenv.

"},{"location":"guide/workspaces/#declaring-workspaces","title":"Declaring Workspaces","text":"

A workspace is declared by the \"toplevel\" pyproject.toml. At the very least the key tool.rye.workspace needs to be added. It's recommended that a glob pattern is also set in the members key to prevent accidentally including unintended folders as projects.

[tool.rye.workspace]\nmembers = [\"myname-*\"]\n

This declares a workspace where all folders starting with the name myname- are considered. If the toplevel workspace in itself should not be a project, then it should be declared as a virtual package:

[tool.rye]\nvirtual = true\n\n[tool.rye.workspace]\nmembers = [\"myname-*\"]\n

For more information on that see Virtual Packages.

"},{"location":"guide/workspaces/#syncing","title":"Syncing","text":"

In a workspace it does not matter which project you are working with, the entire workspace is synchronized at all times. This has some untypical consequences but simplifies the general development workflow.

When a package depends on another package it's first located in the workspace locally before it's attempted to be downloaded from an index. The --all-features flag is automatically applied to all packages, but to turn on the feature of a specific package the feature name must be prefixed. For instance to enable the foo extra feature of the myname-bar package you would need to do this:

rye sync --features=myname-bar/foo\n
"},{"location":"guide/commands/","title":"Commands","text":"

This is a list of all the commands that rye provides:

  • add: Adds a Python package to this project
  • build: Builds a package for distribution
  • config: Reads or updates the Rye configuration
  • fetch: Fetches a Python interpreter for the local machine (alias)
  • fmt: Run the code formatter on the project
  • init: Initializes a new project
  • install: Installs a global tool (alias)
  • lock: Updates the lockfiles without installing dependencies
  • lint: Run the linter on the project
  • make-req: Builds and prints a PEP 508 requirement string from parts
  • pin: Pins a Python version to the project
  • publish: Publish packages to a package repository
  • remove: Remove a dependency from this project
  • run: Runs a command installed into this package
  • show: Prints the current state of the project
  • sync: Updates the virtualenv based on the pyproject.toml
  • toolchain: Helper utility to manage Python toolchains
  • tools: Helper utility to manage global tools.
  • self: Rye self management
  • uninstall: Uninstalls a global tool (alias)
  • version: Get or set project version
"},{"location":"guide/commands/add/","title":"add","text":"

Adds a Python package to this project. The command takes a PEP 508 requirement string but provides additional helper arguments to make this process more user friendly. For instance instead of passing git references within the requiement string, the --git parameter can be used.

If auto sync is disabled, after a dependency is added it's not automatically installed. To do that, you need to invoke the sync command or pass --sync. To remove a dependency again use the remove command.

new in 0.26.0

Added support for auto-sync and the --sync / --no-sync flags.

"},{"location":"guide/commands/add/#example","title":"Example","text":"

Add the latest version of a dependency that is compatible with the configured Python version:

$ rye add flask\nAdded flask>=3.0.1 as regular dependency\n

Add a dependency but add an optional extra feature:

$ rye add flask --features dotenv\nAdded flask[dotenv]>=3.0.1 as regular dependency\n

Add a git dependency:

$ rye add flask --git https://github.com/pallets/flask\nAdded flask @ git+https://github.com/pallets/flask as regular dependency\n

Add a local dependency:

$ rye add packagename --path path/to/packagename\nAdded packagename @ file:///path/to/packagename as regular dependency\n
"},{"location":"guide/commands/add/#arguments","title":"Arguments","text":"
  • <REQUIREMENTS>...: The package to add as PEP 508 requirement string. e.g. 'flask==2.2.3'
"},{"location":"guide/commands/add/#options","title":"Options","text":"
  • --git <GIT>: Install the given package from this git repository

  • --url <URL>: Install the given package from this URL

  • --path <PATH>: Install the given package from this local path

  • --absolute: Force non interpolated absolute paths

  • --tag <TAG>: Install a specific tag

  • --rev <REV>: Update to a specific git rev

  • --branch <BRANCH>: Update to a specific git branch

  • --features <FEATURES>: Adds a dependency with a specific feature

  • --dev: Add this as dev dependency

  • --excluded: Add this as an excluded dependency that will not be installed even if it's a sub dependency

  • --optional <OPTIONAL>: Add this to an optional dependency group

  • --pre: Include pre-releases when finding a package version

  • --pin <PIN>: Overrides the pin operator [possible values: equal, tilde-equal``,greater-than-equal``]

  • --sync: Runs sync automatically even if auto-sync is disabled.

  • --no-sync: Does not run sync automatically even if auto-sync is enabled.

  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/build/","title":"build","text":"

Builds a package for distribution.

Under normal circumstances Rye automatically builds packages for local development. However if you want to publish packages you need to first build them into source distributions (sdist) and binary/portable distributions (wheel).

For more information see Building and Publishing.

"},{"location":"guide/commands/build/#example","title":"Example","text":"

This builds wheels and source distributions at once:

$ rye build\nbuilding my-project\n* Creating virtualenv isolated environment...\n* Installing packages in isolated environment... (hatchling)\n* Getting build dependencies for sdist...\n* Building sdist...\n* Building wheel from sdist\n* Creating virtualenv isolated environment...\n* Installing packages in isolated environment... (hatchling)\n* Getting build dependencies for wheel...\n* Building wheel...\nSuccessfully built my_project-0.1.0.tar.gz and my_project-0.1.0-py3-none-any.whl\n

By default you will find the artifacts in the dist folder.

"},{"location":"guide/commands/build/#arguments","title":"Arguments","text":"

no arguments

"},{"location":"guide/commands/build/#options","title":"Options","text":"
  • --sdist: Build an sdist

  • --wheel: Build a wheel

  • -a, --all: Build all packages

  • -p, --package <PACKAGE>: Build a specific package

  • -o, --out <OUT>: An output directory (defaults to workspace/dist)

  • --pyproject <PYPROJECT_TOML>: Use this `pyproject.toml`` file

  • -c, --clean: Clean the output directory first

  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help

"},{"location":"guide/commands/config/","title":"config","text":"

Reads or modifies the global config.toml file.

The config file can be read via --get and it can be set with one of the set options (--set, --set-int, --set-bool, or --unset). Each of the set operations takes a key=value pair. All of these can be supplied multiple times.

"},{"location":"guide/commands/config/#example","title":"Example","text":"

This command turns on global shims:

rye config --set-bool behavior.global-python=true\n

Reads the currently set config value for global Python shims:

$ rye config --get behavior.global-python\ntrue\n

Show the path to the config:

$ rye config --show-path\n/Users/username/.rye/config.toml\n
"},{"location":"guide/commands/config/#arguments","title":"Arguments","text":"

no arguments

"},{"location":"guide/commands/config/#options","title":"Options","text":"
  • --get <GET>: Reads a config key

  • --set <SET>: Sets a config key to a string

  • --set-int <SET_INT>: Sets a config key to an integer

  • --set-bool <SET_BOOL>: Sets a config key to a bool

  • --unset <UNSET>: Remove a config key

  • --show-path: Print the path to the config

  • --format <FORMAT>: Request parseable output format rather than lines

    [possible values: json]

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/fetch/","title":"fetch","text":"

Fetches a Python interpreter for the local machine. This command is available under the aliases rye fetch and rye toolchain fetch.

"},{"location":"guide/commands/fetch/#example","title":"Example","text":"

Fetch a specific version of Python:

$ rye fetch 3.8.13\nDownloading cpython@3.8.13\nChecking checksum\nUnpacking\nDownloaded cpython@3.8.13\n

To fetch the pinned version of Python you can leave out the argument:

$ rye fetch\nDownloading cpython@3.8.17\nChecking checksum\nUnpacking\nDownloaded cpython@3.8.17\n
"},{"location":"guide/commands/fetch/#arguments","title":"Arguments","text":"
  • [VERSION]: The version of Python to fetch.

    If no version is provided, the requested version will be fetched.

"},{"location":"guide/commands/fetch/#options","title":"Options","text":"
  • -f, --force: Fetch the Python toolchain even if it is already installed.

  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/fmt/","title":"fmt","text":"

new in 0.20.0

Run the code formatter on the project. This command is aliased to format.

For more information about how to configure Ruff, have a look at the Ruff Configuration Documentation.

"},{"location":"guide/commands/fmt/#example","title":"Example","text":"

To format the code and write back to the files:

$ rye fmt\n1 file reformatted, 231 files left unchanged\n

To just check if the code needs formatting:

$ rye fmt --check\nWould reformat: src/my_project/utils.py\n1 file would be reformatted, 231 files already formatted\n

To pass extra arguments to the underlying ruff formatter use --:

$ rye fmt -- --diff\n--- src/my_project/utils.py\n+++ src/my_project/utils.py\n@@ -2,5 +2,4 @@\n\n\n def foo():\n-\n     pass\n\n1 file would be reformatted, 231 files already formatted\n

Format a specific file:

rye fmt src/foo.py\n
"},{"location":"guide/commands/fmt/#arguments","title":"Arguments","text":"
  • [PATHS]... List of files or directories to lint. If not supplied all files are formatted.

  • [EXTRA_ARGS]... Extra arguments to the formatter.

    These arguments are forwarded directly to the underlying formatter (currently always ruff). Note that extra arguments must be separated from other arguments with the -- marker.

"},{"location":"guide/commands/fmt/#options","title":"Options","text":"
  • -a, --all: Format all packages in the workspace

  • -p, --package <PACKAGE>: Format a specific package

  • --pyproject <PYPROJECT_TOML>: Use this pyproject.toml file

  • --check: Run format in check mode

  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/init/","title":"init","text":"

This command initializes a new or existing Python project with Rye. Running it in a folder with an already existing Python project will attempt to convert it over and bootstrap Rye right there. Otherwise it can be used to create a completely new project from scratch.

For more information see the Basics Guide.

"},{"location":"guide/commands/init/#example","title":"Example","text":"
$ rye init\nsuccess: Initialized project in /Users/john/Development/my-project.\n  Run `rye sync` to get started\n
"},{"location":"guide/commands/init/#arguments","title":"Arguments","text":"
  • [PATH]: Where to place the project (defaults to current path)
"},{"location":"guide/commands/init/#options","title":"Options","text":"
  • --min-py <MIN_PY>: Minimal Python version supported by this project

  • -p, --py <PY>: Python version to use for the virtualenv

  • --no-readme: Do not create a readme

  • --no-pin: Do not create .python-version file (requires-python will be used)

  • --build-system <BUILD_SYSTEM>: Which build system should be used(defaults to hatchling)?

    [possible values: hatchling, setuptools, flit, pdm, maturin]

  • --license <LICENSE>: Which license should be used? SPDX identifier

  • --name <NAME>: The name of the package

  • --private: Set \"Private :: Do Not Upload\" classifier, used for private projects

  • --no-import: Don't import from setup.cfg, setup.py, or requirements files

  • --virtual: Initialize this as a virtual package.

    A virtual package can have dependencies but is itself not installed as a Python package. It also cannot be published.

  • -r, --requirements <REQUIREMENTS_FILE>: Requirements files to initialize pyproject.toml with

  • --dev-requirements <DEV_REQUIREMENTS_FILE>: Development requirements files to initialize pyproject.toml with

  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/install/","title":"install","text":"

Installs a package as global tool. This command has two names to rye tools install and rye install.

This can be used to install useful Python scripts globally into it's own separated virtualenv. For instance if you want to use the black formatter you can install it once.

Normally only scripts installed by the top level dependency are installed. In some cases you might also want to install commands from sub-dependencies. In that case pass those dependencies with --include-dep.

For more information see Tools.

"},{"location":"guide/commands/install/#example","title":"Example","text":"
$ rye tools install pycowsay\nLooking in indexes: https://pypi.org/simple/\nCollecting pycowsay\n  Downloading pycowsay-0.0.0.2-py3-none-any.whl.metadata (965 bytes)\nDownloading pycowsay-0.0.0.2-py3-none-any.whl (4.0 kB)\nInstalling collected packages: pycowsay\nSuccessfully installed pycowsay-0.0.0.2\n\nInstalled scripts:\n  - pycowsay\n\n$ pycowsay \"Great Stuff\"\n\n  -----------\n< Great Stuff >\n  -----------\n   \\   ^__^\n    \\  (oo)\\_______\n       (__)\\       )\\/\\\n           ||----w |\n           ||     ||\n
"},{"location":"guide/commands/install/#arguments","title":"Arguments","text":"
  • <REQUIREMENT>...: The package to install as PEP 508 requirement string.
"},{"location":"guide/commands/install/#options","title":"Options","text":"
  • --git <GIT>: Install the given package from this git repository

  • --url <URL>: Install the given package from this URL

  • --path <PATH>: Install the given package from this local path

  • --absolute: Force non interpolated absolute paths

  • --tag <TAG>: Install a specific tag

  • --rev <REV>: Update to a specific git rev

  • --branch <BRANCH>: Update to a specific git branch

  • --features <FEATURES>: Adds a dependency with a specific feature

  • --include-dep <INCLUDE_DEP>: Include scripts from a given dependency

  • --extra-requirement <EXTRA_REQUIREMENT>: Additional dependencies to install that are not declared by the main package

  • -p, --python <PYTHON>: Optionally the Python version to use

  • -f, --force: Force install the package even if it's already there

  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/lint/","title":"lint","text":"

new in 0.20.0

Run the linter on the project. This command is aliased to check. At the moment this always runs ruff in lint mode.

For more information about how to configure Ruff, have a look at the Ruff Configuration Documentation.

"},{"location":"guide/commands/lint/#example","title":"Example","text":"

Run the linter:

$ rye lint\nsrc/myproject/sdk.py:1:8: F401 [*] `sys` imported but unused\nFound 1 error.\n[*] 1 fixable with the `--fix` option.\n

For issues that can be auto fixed pass --fix:

$ rye lint --fix\nFound 1 error (1 fixed, 0 remaining).\n

To pass extra arguments:

$ rye lint -- --watch\n

Lint a specific file:

rye lint src/foo.py\n
"},{"location":"guide/commands/lint/#arguments","title":"Arguments","text":"
  • [PATHS]... List of files or directories to lint. If not supplied all files are linted.

  • [EXTRA_ARGS]... Extra arguments to the linter.

    These arguments are forwarded directly to the underlying linter (currently always ruff). Note that extra arguments must be separated from other arguments with the -- marker.

"},{"location":"guide/commands/lint/#options","title":"Options","text":"
  • -a, --all: Lint all packages in the workspace

  • -p, --package <PACKAGE>: Format a specific package

  • --pyproject <PYPROJECT_TOML>: Use this pyproject.toml file

  • --fix: Automatically fix fixable issues

  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/list/","title":"list","text":"

new in 0.24.0

Prints a list of installed dependencies.

"},{"location":"guide/commands/list/#example","title":"Example","text":"
$ rye list\nasgiref==3.7.2\nblinker==1.7.0\nclick==8.1.7\nFlask @ git+https://github.com/pallets/flask@4df377cfbfc1d15e962a61c18920b22aebc9aa41\nitsdangerous==2.1.2\nJinja2==3.1.3\nMarkupSafe==2.1.4\nWerkzeug==3.0.1\n
"},{"location":"guide/commands/list/#arguments","title":"Arguments","text":"

no arguments

"},{"location":"guide/commands/list/#options","title":"Options","text":"
  • --pyproject: Use this pyproject.toml file

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/lock/","title":"lock","text":"

Updates the lockfiles without installing dependencies. Usually one would use the sync command instead which both locks and installs dependencies.

For more information see Synching and Locking.

"},{"location":"guide/commands/lock/#example","title":"Example","text":"
$ rye lock\nGenerating production lockfile: /Users/username/my-project/requirements.lock\nGenerating dev lockfile: /Users/username/my-project/requirements-dev.lock\nDone!\n
"},{"location":"guide/commands/lock/#arguments","title":"Arguments","text":"

no arguments

"},{"location":"guide/commands/lock/#options","title":"Options","text":"
  • --update <UPDATE>: Update a specific package

  • --update-all: Update all packages to the latest

  • --pre: Update to pre-release versions

  • --features <FEATURES>: Extras/features to enable when locking the workspace

  • --all-features: Enables all features

  • --with-sources: Set to true to lock with sources in the lockfile

  • --pyproject <PYPROJECT_TOML>: Use this pyproject.toml file

  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/make-req/","title":"make-req","text":"

Builds and prints a PEP 508 requirement string from parts. This is a utility command that rarely needs to be used but can help creating requirements strings for pasting into other tools. It takes the same arguments as add but rather than adding the requirements into the requirements file it just spits out a formatted PEP 508 requirement string on stdout.

"},{"location":"guide/commands/make-req/#example","title":"Example","text":"
$ rye make-req flask --git https://github.com/pallets/flask --rev 4df377cfbf\nflask @ git+https://github.com/pallets/flask@4df377cfbf\n
"},{"location":"guide/commands/make-req/#arguments","title":"Arguments","text":"
  • [REQUIREMENTS]... The package to add as PEP 508 requirement string. e.g. 'flask==2.2.3'
"},{"location":"guide/commands/make-req/#options","title":"Options","text":"
  • --git <GIT>: Install the given package from this git repository

  • --url <URL>: Install the given package from this URL

  • --path <PATH>: Install the given package from this local path

  • --absolute: Force non interpolated absolute paths

  • --tag <TAG>: Install a specific tag

  • --rev <REV>: Update to a specific git rev

  • --branch <BRANCH>: Update to a specific git branch

  • --features <FEATURES>: Adds a dependency with a specific feature

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/pin/","title":"pin","text":"

Pins a Python version to this project.

This will update the .python-version to point to the provided version. Additionally it will update requires-python in the pyproject.toml if it's lower than the current version. This can be disabled by passing --no-update-requires-python.

Which toolchain Rye prefers depends on the Rye version. From 0.22 onwards the latest compatible installed toolchain is picked, and only if a non existing one is found a download will be attempted. For older versions Rye will always attempt to download the latest available if it's not installed yet unless a precise pin is selected.

"},{"location":"guide/commands/pin/#example","title":"Example","text":"

Pin a specific version of Python:

$ rye pin 3.9\npinned 3.9.18 in /Users/username/my-project\n

To issue a relaxed and not a specific pin use --relaxed:

$ rye pin 3.9 --relaxed\npinned 3.9 in /Users/username/my-project\n
"},{"location":"guide/commands/pin/#arguments","title":"Arguments","text":"
  • <VERSION>: The version of Python to pin

    This can be a short version (3.9) or a full one (cpython@3.9.18).

"},{"location":"guide/commands/pin/#options","title":"Options","text":"
  • --relaxed: Issue a relaxed pin

  • --no-update-requires-python: Prevent updating requires-python in the pyproject.toml

  • --pyproject <PYPROJECT_TOML>: Use this pyproject.toml file

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/publish/","title":"publish","text":"

Publish packages to a package repository. This publishes the packages which are produced by the build command.

For more information see Building and Publishing.

"},{"location":"guide/commands/publish/#example","title":"Example","text":"

Build and publish:

$ rye build\n$ rye publish\n

Publish a specific artifact:

$ rye publish dist/example-0.1.0.tar.gz\n
"},{"location":"guide/commands/publish/#arguments","title":"Arguments","text":"
  • [DIST]...: The distribution files to upload to the repository (defaults to <workspace-root>/dist/*)
"},{"location":"guide/commands/publish/#options","title":"Options","text":"
  • -r, --repository <REPOSITORY>: The repository to publish to [default: pypi]

  • --repository-url <REPOSITORY_URL>: The repository url to publish to

  • -u, --username <USERNAME>: The username to authenticate to the repository with

  • --token <TOKEN>: An access token used for the upload

  • --sign: Sign files to upload using GPG

  • -i, --identity <IDENTITY>: GPG identity used to sign files

  • --cert <CERT>: Path to alternate CA bundle

  • --skip-existing: Skip files already published (repository must support this feature)

  • -y, --yes: Skip prompts

  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/remove/","title":"remove","text":"

Removes a package from this project. This removes a package from the pyproject.toml dependency list.

If auto sync is disabled, after a dependency is removed it's not automatically uninstalled. To do that, you need to invoke the sync command or pass --sync.

new in 0.26.0

Added support for auto-sync and the --sync / --no-sync flags.

"},{"location":"guide/commands/remove/#example","title":"Example","text":"
$ rye remove flask\nRemoved flask>=3.0.1\n
"},{"location":"guide/commands/remove/#arguments","title":"Arguments","text":"
  • <REQUIREMENTS>...: The packages to remove from the project
"},{"location":"guide/commands/remove/#options","title":"Options","text":"
  • --dev: Remove this from dev dependencies

  • --optional <OPTIONAL>: Remove this from the optional dependency group

  • --sync: Runs sync automatically even if auto-sync is disabled.

  • --no-sync: Does not run sync automatically even if auto-sync is enabled.

  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/run/","title":"run","text":"

Runs a command installed into this package. This either runs a script or application made available in the virtualenv or a Rye specific script.

For more information see rye.tool.scripts.

"},{"location":"guide/commands/run/#example","title":"Example","text":"

Run a tool from the virtualenv:

$ rye run flask\n

Invoke it without arguments to see all available scripts:

$ rye run\nflask\nhello\npython\npython3\npython3.9\n
"},{"location":"guide/commands/run/#arguments","title":"Arguments","text":"
  • [COMMAND]: The name of the command and the arguments to it.
"},{"location":"guide/commands/run/#options","title":"Options","text":"
  • -l, --list: List all commands (implied without arguments)

  • --pyproject: Use this pyproject.toml file

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/show/","title":"show","text":"

Prints the current state of the project. This can print out information about the virtualenv, the project or workspace as well as a list of installed dependencies.

"},{"location":"guide/commands/show/#example","title":"Example","text":"

Print out the status of a project:

$ rye show\nproject: my-project\npath: /Users/username/my-project\nvenv: /Users/username/my-project/.venv\ntarget python: 3.8\nvenv python: cpython@3.9.18\nvirtual: false\n
"},{"location":"guide/commands/show/#arguments","title":"Arguments","text":"

no arguments

"},{"location":"guide/commands/show/#options","title":"Options","text":"
  • --installed-deps: Print the currently installed dependencies.

    This option is being replaced with rye list

  • --pyproject: Use this pyproject.toml file

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/sync/","title":"sync","text":"

Updates the lockfiles and installs the dependencies into the virtualenv.

For more information see Synching and Locking.

"},{"location":"guide/commands/sync/#example","title":"Example","text":"

Sync the project:

$ rye sync\nReusing already existing virtualenv\nGenerating production lockfile: /Users/username/my-project/requirements.lock\nGenerating dev lockfile: /Users/username/my-project/requirements-dev.lock\nInstalling dependencies\n...\n

To sync without updating the lock file use --no-lock:

$ rye sync --no-lock\n

If you do not want dev dependencies to be installed use --no-dev:

$ rye sync --no-dev\n

To exit the sub shell run exit.

"},{"location":"guide/commands/sync/#arguments","title":"Arguments","text":"

no arguments

"},{"location":"guide/commands/sync/#options","title":"Options","text":"
  • -f, --force: Force the virtualenv to be re-created

  • --no-dev: Do not install dev dependencies

  • --no-lock: Do not update the lockfile.

  • --update <UPDATE>: Update a specific package

  • --update-all: Update all packages to the latest

  • --pre: Update to pre-release versions

  • --features <FEATURES>: Extras/features to enable when locking the workspace

  • --all-features: Enables all features

  • --with-sources: Set to true to lock with sources in the lockfile

  • --pyproject <PYPROJECT_TOML>: Use this pyproject.toml file

  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/uninstall/","title":"uninstall","text":"

Uninstalls an already installed global tool. This command has two names to rye tools uninstall and rye uninstall.

For more information see Tools.

"},{"location":"guide/commands/uninstall/#example","title":"Example","text":"
$ rye tools uninstall pycowsay\nUninstalled pycowsay\n
"},{"location":"guide/commands/uninstall/#arguments","title":"Arguments","text":"
  • <NAME>: The package to uninstall.
"},{"location":"guide/commands/uninstall/#options","title":"Options","text":"
  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/version/","title":"version","text":"

Get or set project version. Note that this does not refer to the version of Rye itself but the version that is set in the pyproject.toml file.

"},{"location":"guide/commands/version/#example","title":"Example","text":"

Get the current version:

$ rye version\n0.1.0\n

Bump the version by minor:

$ rye version -b minor\nversion bumped to 0.2.0\n

Set to a specific version:

$ rye version 1.0.0\nversion set to 1.0.0\n
"},{"location":"guide/commands/version/#arguments","title":"Arguments","text":"
  • [VERSION]: the version to set
"},{"location":"guide/commands/version/#options","title":"Options","text":"
  • -b, --bump <BUMP>: automatically bump the version in a specific way (major, minor or patch)

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/self/","title":"self","text":"

Command to manage Rye itself.

  • completion: Generates a completion script for Rye.

  • update: Performs an update of Rye.

  • uninstall: Uninstalls Rye again.

"},{"location":"guide/commands/self/completion/","title":"completion","text":"

Generates a completion script for a shell

"},{"location":"guide/commands/self/completion/#example","title":"Example","text":"

Generate a completion script for zsh and load it:

$ eval (rye self completion -s zsh)\n
"},{"location":"guide/commands/self/completion/#arguments","title":"Arguments","text":"

no arguments

"},{"location":"guide/commands/self/completion/#options","title":"Options","text":"
  • -s, --shell <SHELL>: The shell to generate a completion script for (defaults to 'bash')

    [possible values: bash, elvish, fish, powershell, zsh]

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/self/uninstall/","title":"uninstall","text":"

Uninstalls rye again. Note that this leaves a trace .rye folder behind with an empty env file. You also need to remove the sourcing of that script from your .profile file.

"},{"location":"guide/commands/self/uninstall/#example","title":"Example","text":"

Uninstall rye without asking:

$ rye self uninstall --yes\n
"},{"location":"guide/commands/self/uninstall/#arguments","title":"Arguments","text":"

no arguments

"},{"location":"guide/commands/self/uninstall/#options","title":"Options","text":"
  • -y, --yes: Do not prompt and uninstall.

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/self/update/","title":"update","text":"

Performs an update of rye.

This can install updates from the latest release binaries or trigger a manual compilation of Rye if Rust is installed.

"},{"location":"guide/commands/self/update/#example","title":"Example","text":"

Update to the latest version:

$ rye self update\n

Update (or downgrade) to a specific version:

$ rye self update --version 0.20\n

Compile a specific revision:

$ rye self update --rev 08910bc9b3b7c72a3d3ac694c4f3412259161477\n
"},{"location":"guide/commands/self/update/#arguments","title":"Arguments","text":"

no arguments

"},{"location":"guide/commands/self/update/#options","title":"Options","text":"
  • --version <VERSION>: Update to a specific version

  • --tag <TAG>: Update to a specific tag

  • --rev <REV>: Update to a specific git rev

  • --force: Force reinstallation

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/toolchain/","title":"toolchain","text":"

Helper utility to manage Python toolchains. The following subcommands exist:

  • fetch: fetches a toolchain

  • list: lists all registered toolchains

  • register: register a Python binary as custom toolchain

  • remove: removes or uninstalls a toolchain

"},{"location":"guide/commands/toolchain/fetch/","title":"fetch","text":"

Fetches a Python interpreter for the local machine. This command is available under the aliases rye fetch and rye toolchain fetch.

"},{"location":"guide/commands/toolchain/fetch/#example","title":"Example","text":"

Fetch a specific version of Python:

$ rye fetch 3.8.13\nDownloading cpython@3.8.13\nChecking checksum\nUnpacking\nDownloaded cpython@3.8.13\n

To fetch the pinned version of Python you can leave out the argument:

$ rye fetch\nDownloading cpython@3.8.17\nChecking checksum\nUnpacking\nDownloaded cpython@3.8.17\n
"},{"location":"guide/commands/toolchain/fetch/#arguments","title":"Arguments","text":"
  • [VERSION]: The version of Python to fetch.

    If no version is provided, the requested version will be fetched.

"},{"location":"guide/commands/toolchain/fetch/#options","title":"Options","text":"
  • -f, --force: Fetch the Python toolchain even if it is already installed.

  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/toolchain/list/","title":"list","text":"

List all registered toolchains. It can list the toolchains which are installed as well as toolchains which can be downloaded if --include-downloadable is passed.

"},{"location":"guide/commands/toolchain/list/#example","title":"Example","text":"

List installed toolchains:

$ rye toolchain list\ncpython@3.12.1 (/Users/username/.rye/py/cpython@3.12.1/install/bin/python3)\ncpython@3.11.6 (/Users/username/.rye/py/cpython@3.11.6/install/bin/python3)\n

Lists downloadable toolchains:

$ rye toolchain list --include-downloadable\ncpython@3.12.1 (/Users/mitsuhiko/.rye/py/cpython@3.12.1/install/bin/python3)\ncpython-x86_64@3.12.1 (downloadable)\ncpython@3.11.7 (downloadable)\n...\n
"},{"location":"guide/commands/toolchain/list/#arguments","title":"Arguments","text":"

no arguments

"},{"location":"guide/commands/toolchain/list/#options","title":"Options","text":"
  • --include-downloadable: Also include non installed, but downloadable toolchains

  • --format <FORMAT>: Request parseable output format [possible values: json]

  • -h, --help: Print help

"},{"location":"guide/commands/toolchain/register/","title":"register","text":"

Register a Python binary as custom toolchain.

Rye by default will automatically download Python releases from the internet. However it's also possible to register already available local Python installations. This allows you to use rye with self compiled Pythons.

The name of the toolchain is auto detected (eg: cpython, pypy etc.)

To unregister use the remove command.

"},{"location":"guide/commands/toolchain/register/#example","title":"Example","text":"
$ rye toolchain register /opt/homebrew/Cellar/python@3.10/3.10.6_1/bin/python3.10\nRegistered /opt/homebrew/Cellar/python@3.10/3.10.6_1/bin/python3.10 as cpython@3.10.6\n
"},{"location":"guide/commands/toolchain/register/#arguments","title":"Arguments","text":"
  • <PATH>: Path to the python binary that should be registered
"},{"location":"guide/commands/toolchain/register/#options","title":"Options","text":"
  • -n, --name <NAME>: Name of the toolchain. If not provided a name is auto detected.

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/toolchain/remove/","title":"remove","text":"

Removes or uninstalls a toolchain.

"},{"location":"guide/commands/toolchain/remove/#example","title":"Example","text":"
$ rye toolchain remove 3.9.5\nRemoved installed toolchain cpython@3.9.5\n
"},{"location":"guide/commands/toolchain/remove/#arguments","title":"Arguments","text":"
  • <VERSION> The version of Python to remove.
"},{"location":"guide/commands/toolchain/remove/#options","title":"Options","text":"
  • -f, --force: Force removal even if the toolchain is in use
  • -h, --help: Print help (see a summary with '-h')
"},{"location":"guide/commands/tools/","title":"tools","text":"

Helper utility to manage global tool installations.

  • install: installs a tool globally.

  • uninstall: uninstalls a globally installed tool.

  • list: lists all globally installed tools.

"},{"location":"guide/commands/tools/install/","title":"install","text":"

Installs a package as global tool. This command has two names to rye tools install and rye install.

This can be used to install useful Python scripts globally into it's own separated virtualenv. For instance if you want to use the black formatter you can install it once.

Normally only scripts installed by the top level dependency are installed. In some cases you might also want to install commands from sub-dependencies. In that case pass those dependencies with --include-dep.

For more information see Tools.

"},{"location":"guide/commands/tools/install/#example","title":"Example","text":"
$ rye tools install pycowsay\nLooking in indexes: https://pypi.org/simple/\nCollecting pycowsay\n  Downloading pycowsay-0.0.0.2-py3-none-any.whl.metadata (965 bytes)\nDownloading pycowsay-0.0.0.2-py3-none-any.whl (4.0 kB)\nInstalling collected packages: pycowsay\nSuccessfully installed pycowsay-0.0.0.2\n\nInstalled scripts:\n  - pycowsay\n\n$ pycowsay \"Great Stuff\"\n\n  -----------\n< Great Stuff >\n  -----------\n   \\   ^__^\n    \\  (oo)\\_______\n       (__)\\       )\\/\\\n           ||----w |\n           ||     ||\n
"},{"location":"guide/commands/tools/install/#arguments","title":"Arguments","text":"
  • <REQUIREMENT>...: The package to install as PEP 508 requirement string.
"},{"location":"guide/commands/tools/install/#options","title":"Options","text":"
  • --git <GIT>: Install the given package from this git repository

  • --url <URL>: Install the given package from this URL

  • --path <PATH>: Install the given package from this local path

  • --absolute: Force non interpolated absolute paths

  • --tag <TAG>: Install a specific tag

  • --rev <REV>: Update to a specific git rev

  • --branch <BRANCH>: Update to a specific git branch

  • --features <FEATURES>: Adds a dependency with a specific feature

  • --include-dep <INCLUDE_DEP>: Include scripts from a given dependency

  • --extra-requirement <EXTRA_REQUIREMENT>: Additional dependencies to install that are not declared by the main package

  • -p, --python <PYTHON>: Optionally the Python version to use

  • -f, --force: Force install the package even if it's already there

  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/commands/tools/list/","title":"list","text":"

Lists all already installed global tools.

For more information see Tools.

"},{"location":"guide/commands/tools/list/#example","title":"Example","text":"

List installed tools:

$ rye tools list\npycowsay\n

List installed tools with version:

$ rye tools list --include-version\npycowsay 0.0.0.2 (cpython@3.12.1)\n
"},{"location":"guide/commands/tools/list/#arguments","title":"Arguments","text":"

no arguments

"},{"location":"guide/commands/tools/list/#options","title":"Options","text":"
  • -s, --include-scripts: Show all the scripts installed by the tools

changed in 0.26.0

Renamed from -i, --include-scripts to -s, --include-scripts.

  • -v, --include-version: Show the version of tools

changed in 0.26.0

Renamed from -v, --version-show to -v, --include-version.

  • -h, --help: Print help
"},{"location":"guide/commands/tools/uninstall/","title":"uninstall","text":"

Uninstalls an already installed global tool. This command has two names to rye tools uninstall and rye uninstall.

For more information see Tools.

"},{"location":"guide/commands/tools/uninstall/#example","title":"Example","text":"
$ rye tools uninstall pycowsay\nUninstalled pycowsay\n
"},{"location":"guide/commands/tools/uninstall/#arguments","title":"Arguments","text":"
  • <NAME>: The package to uninstall.
"},{"location":"guide/commands/tools/uninstall/#options","title":"Options","text":"
  • -v, --verbose: Enables verbose diagnostics

  • -q, --quiet: Turns off all output

  • -h, --help: Print help (see a summary with '-h')

"},{"location":"guide/toolchains/","title":"Toolchain Management","text":"

Rye is unique in that it does not use system Python installations. Instead it downloads and manages Python installations itself (called toolchains). Today there are three types of toolchains supported by Rye and they require some understanding:

  • Portable CPython: Rye will itself download portable builds of CPython for most of its needs. These are fetched from indygreg/python-build-standalone
  • Official PyPy Builds: PyPy is supported from the official release builds.
  • Custom Local Toolchains: locally installed Python interpreters can be registered with Rye. Afterwards, they can be used with any Rye managed project.
"},{"location":"guide/toolchains/#pinning-toolchains","title":"Pinning Toolchains","text":"

To make a project use a specific toolchain write the name of the toolchain into the .python-version file or use the pin command. For pinning cpython the cpython@ prefix can be omitted.

rye pin cpython@3.11.4\n

Pinning a downloadable version means that Rye will automatically fetch it when necessary. By default, toolchains are pinned to a precise version. This means that even if you write rye pin cpython@3.11, a very specific version of cpython is written into the .python-version file. With Rye 0.5.0 onwards it's possible to perform \"relaxed\" pins:

rye pin --relaxed cpython@3.11\n

This will then persist 3.11 in the .python-version file and Rye will use the latest available compatible version for the virtual environment.

changed in 0.5.0

Relaxed pinning with rye pin --relaxed was added.

"},{"location":"guide/toolchains/#non-native-architectures","title":"Non Native Architectures","text":"

new in 0.14.0

Support for fetching and pinning of non-native architectures was added.

By default, the pin is for the architecture of the running machine. This means that if you pin cpython@3.11 on a mac with aarch64 architecture, you will use a cpython interpreter of that CPU architecture. A different architecture can be selected by adding -{arch} to the python family name. So for instance to force a x86_64 version you need to pin like this:

rye pin cpython-x86_64@3.11\n

Note that such custom pins are not reflected in pyproject.toml but only .python-version.

"},{"location":"guide/toolchains/#listing-toolchains","title":"Listing Toolchains","text":"

To see which toolchains are installed, rye toolchain list prints a list:

rye toolchain list\n
cpython@3.11.1 (C:\\Users\\armin\\.rye\\py\\cpython@3.11.1\\install\\python.exe)\npypy@3.9.16 (C:\\Users\\armin\\.rye\\py\\pypy@3.9.16\\python.exe)\n

To see which toolchains can be installed, additionally pass the --include-downloadable:

rye toolchain list --include-downloadable\n
"},{"location":"guide/toolchains/#fetching-toolchains","title":"Fetching Toolchains","text":"

Generally Rye automatically downloads toolchains, but they can be explicitly fetched with rye toolchain fetch (also aliased to rye fetch):

rye toolchain fetch cpython@3.8.5\n

Starting with Rye 0.19.0 the argument to fetch is inferred from the current pin. This means you can also fetch as follows:

rye pin 3.10\nrye fetch\n

Toolchains are fetched from two sources:

  • Indygreg's Portable Python Builds for CPython
  • PyPy.org for PyPy
"},{"location":"guide/toolchains/#registering-toolchains","title":"Registering Toolchains","text":"

Additionally, it's possible to register an external toolchain with the rye toolchain register command.

rye toolchain register /path/to/python\n

The name of the toolchain is picked based on the interpreter. For instance linking a regular cpython installation will be called cpython@version, whereas linking pypy would show up as pypy@version. From Rye 0.5.0 onwards -dbg is appended to the name of the toolchain if it's a debug build. To override the name you can pass --name:

rye toolchain register --name=custom /path/to/python\n
"},{"location":"guide/toolchains/#removing-toolchains","title":"Removing Toolchains","text":"

To remove an already fetched toolchain run rye toolchain remove. Note that this also works for linked toolchains:

rye toolchain remove cpython@3.8.5\n

Warning

Removing an actively used toolchain will render the virtualenvs that refer to use broken.

"},{"location":"guide/toolchains/cpython/","title":"Portable CPython","text":"

Rye is capable (and prefers) to download its own Python distribution over what you might already have on your computer. For CPython, the indygreg/python-build-standalone builds from the PyOxidizer project are used.

The motivation for this is that it makes it easy to switch between Python versions, to have a common experience across different Rye users and to avoid odd bugs caused by changes in behavior.

Unfortunately Python itself does not release binaries (or the right types of binaries) for all operating systems which is why Rye leverages the portable Python builds from PyOxidizer.

Unlike many other Python versions you can install on your computer are non-portable which means that if you move them to a new location on your machine, or you copy it onto another computer (even with the same operating system) they will no longer run. This is undesirable for what Rye wants to do. For one we want the same experience for any of the Python developers, no matter which operating system they used. Secondly we want to enable self-contained Python builds later, which requires that the Python installation is portable.

To achieve this, the Python builds we use come with some changes that are different from a regular Python build.

"},{"location":"guide/toolchains/cpython/#limitations","title":"Limitations","text":"

The following changes to a regular Python versions you should be aware of:

  • libedit instead of readline: unfortunately readline is GPL2 licensed and this is a hazard for redistributions. As such, the portable Python builds link against the more freely licensed libedit instead.

  • dbm.gnu is unavailable. This is a rather uncommonly used module and the standard library provides alternatives.

Additionally due to how these builds are created, there are some other quirks you might run into related to terminal support or TKinter. Some of these issues are collected in the FAQ. Additionally the Python Standalone Builds have a Behavior Quirks page.

"},{"location":"guide/toolchains/cpython/#sources","title":"Sources","text":"

Portable CPython builds are downloaded from GitHub (indygreg/python-build-standalone/releases) and SHA256 hashes are generally validated. Some older versions might not have hashes available in which case the validation is skipped.

"},{"location":"guide/toolchains/cpython/#usage","title":"Usage","text":"

When you pin a Python version to cpython@major.minor.patch (or just major.minor.patch) then Rye will automatically download the right version for you whenever it is needed. If a custom toolchain has already been registered with that name and version, that this is used instead.

"},{"location":"guide/toolchains/pypy/","title":"PyPy","text":"

PyPy is supported as alternative Python distribution. Like the portable CPython builds it's downloaded automatically. The name for PyPy distributions is pypy.

"},{"location":"guide/toolchains/pypy/#limitations","title":"Limitations","text":"

PyPy has some limitations compared to regular Python builds when it comes to working with Rye. Most specifically PyPy uses some internal pypi dependencies and you might notice warnings show up when syching. PyPy also lags behind regular Python installations quite a bit these days so you likely need to target older Python packages.

"},{"location":"guide/toolchains/pypy/#sources","title":"Sources","text":"

PyPy builds are downloaded from downloads.python.org.

"},{"location":"guide/toolchains/pypy/#usage","title":"Usage","text":"

When you pin a Python version to pypy@major.minor.patch then Rye will automatically download the right version for you whenever it is needed. If a custom toolchain has already been registered with that name and version, that this is used instead. Note that the version refers to the PyPy CPython version.

That means for instance that PyPy 7.3.11 is identified as pypy@3.9.16 as this is the Python version it provides. As PyPy also lacks builds for some CPU architectures, not all platforms might provide the right PyPy versions.

"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml new file mode 100644 index 0000000000..0f8724efd9 --- /dev/null +++ b/sitemap.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..d9cf78724ccb41045bca37e6838f8f57931c28e1 GIT binary patch literal 127 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

I8KLq=fAX`(j>> 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 literal 0 HcmV?d00001 diff --git a/static/extra.css b/static/extra.css new file mode 100644 index 0000000000..ed9751a21a --- /dev/null +++ b/static/extra.css @@ -0,0 +1,104 @@ +[data-md-color-scheme="default"], +:root { + --md-primary-fg-color: #7C9F35; + --md-primary-fg-color--light: #ADC541; + --md-primary-fg-color--dark: #9BB029; + --md-accent-fg-color: #54780d; +} + +[data-md-color-scheme="slate"] { + --md-hue: 190; + --md-accent-fg-color: #90c820; +} + +.md-header { + background: url(/static/banner.png) repeat-x; + background-color: var(--md-primary-fg-color); + background-size: 605px 75px; +} + +nav.md-tabs { + background: url(/static/banner-dark.png) repeat-x; + background-color: transparent; + background-size: 605px 75px; +} + +[data-md-component="palette"] { + display: none; +} + +/* version changed */ +:root { + /* Icon for "version-added" admonition: Material Design Icons "plus-box-outline" */ + --md-admonition-icon--version-added: url('data:image/svg+xml;charset=utf-8,'); + /* Icon for "version-changed" admonition: Material Design Icons "delta" */ + --md-admonition-icon--version-changed: url('data:image/svg+xml;charset=utf-8,'); + /* Icon for "version-removed" admonition: Material Design Icons "minus-circle-outline" */ + --md-admonition-icon--version-removed: url('data:image/svg+xml;charset=utf-8,'); +} + +.md-typeset .admonition.version-added, +.md-typeset .admonition.version-changed, +.md-typeset .admonition.version-removed { + border-radius: 3px; +} + +.md-typeset .admonition.version-added p.admonition-title, +.md-typeset .admonition.version-changed p.admonition-title, +.md-typeset .admonition.version-removed p.admonition-title { + font-weight: normal; +} + +/* "version-added" admonition in green */ +.md-typeset .admonition.version-added, +.md-typeset details.version-added { + border-color: rgb(11, 129, 38); +} + +.md-typeset .version-added>.admonition-title, +.md-typeset .version-added>summary { + background-color: rgba(4, 91, 40, 0.1); +} + +.md-typeset .version-added>.admonition-title::before, +.md-typeset .version-added>summary::before { + background-color: rgb(0, 200, 83); + -webkit-mask-image: var(--md-admonition-icon--version-added); + mask-image: var(--md-admonition-icon--version-added); +} + +/* "version-changed" admonition in orange */ +.md-typeset .admonition.version-changed, +.md-typeset details.version-changed { + border-color: rgb(255, 145, 0); +} + +.md-typeset .version-changed>.admonition-title, +.md-typeset .version-changed>summary { + background-color: rgba(255, 145, 0, .1); +} + +.md-typeset .version-changed>.admonition-title::before, +.md-typeset .version-changed>summary::before { + background-color: rgb(255, 145, 0); + -webkit-mask-image: var(--md-admonition-icon--version-changed); + mask-image: var(--md-admonition-icon--version-changed); +} + +/* "version-removed" admonition in red */ +.md-typeset .admonition.version-removed, +.md-typeset details.version-removed { + border-color: rgb(255, 82, 82); +} + +.md-typeset .version-removed>.admonition-title, +.md-typeset .version-removed>summary { + background-color: rgba(255, 82, 82, .1); +} + +.md-typeset .version-removed>.admonition-title::before, +.md-typeset .version-removed>summary::before { + background-color: rgb(255, 82, 82); + -webkit-mask-image: var(--md-admonition-icon--version-removed); + mask-image: var(--md-admonition-icon--version-removed); +} \ No newline at end of file diff --git a/static/favicon.svg b/static/favicon.svg new file mode 100644 index 0000000000..54cf6c428f --- /dev/null +++ b/static/favicon.svg @@ -0,0 +1,14 @@ + + + + + + + diff --git a/static/logo-auto.svg b/static/logo-auto.svg new file mode 100644 index 0000000000..6e4e5f3933 --- /dev/null +++ b/static/logo-auto.svg @@ -0,0 +1,14 @@ + + + + + + + diff --git a/static/logo.svg b/static/logo.svg new file mode 100644 index 0000000000..e5f9906c95 --- /dev/null +++ b/static/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file