mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[python][hatch] add HatchService (PY-60410)
HatchService is the middle layer API and has the CliBasedHatchService implementation. For now it allows to: * manage virtual environments * detect if the project is managed by Hatch (hatch.toml or [tool.hatch.*] sections in project.toml) * create a new project structure (might be reused in 'welcome script' on new projects) GitOrigin-RevId: f19210180e69bfd968bcc4cfdcf3a1b7925e3841
This commit is contained in:
committed by
intellij-monorepo-bot
parent
37dcd01f72
commit
ba56847745
@@ -14,5 +14,5 @@ public final class PythonHatchIcons {
|
||||
private static @NotNull Icon load(@NotNull String path, int cacheKey, int flags) {
|
||||
return IconManager.getInstance().loadRasterizedIcon(path, PythonHatchIcons.class.getClassLoader(), cacheKey, flags);
|
||||
}
|
||||
/** 16x16 */ public static final @NotNull Icon Logo = load("icons/com/intellij/python/hatch/expui/logo.svg", 1803583895, 0);
|
||||
/** 16x16 */ public static final @NotNull Icon Logo = load("icons/com/intellij/python/hatch/expui/logo.svg", 1919219635, 0);
|
||||
}
|
||||
|
||||
@@ -41,5 +41,7 @@
|
||||
<orderEntry type="module" module-name="intellij.python.community" />
|
||||
<orderEntry type="module" module-name="intellij.python.community.execService" />
|
||||
<orderEntry type="library" name="io.github.z4kn4fein.semver.jvm" level="project" />
|
||||
<orderEntry type="module" module-name="intellij.platform.projectModel" />
|
||||
<orderEntry type="module" module-name="intellij.python.sdk" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,74 +1,77 @@
|
||||
<svg width="16" height="16" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M543.5 406.195L549 369.195L492 392.695L428 421.695L445 433.695L508 440.195L543.5 406.195Z" fill="url(#paint0_linear_5_2)"/>
|
||||
<path d="M556.5 299.195L608.5 332.695L591 351.195L556.5 363.695L530.5 377.695L491 393.695L439.5 416.195L390.5 427.695L400 391.195L317 377.695L294 357.695L286 299.195L299.5 286.195L341.5 250.695L366 234.695L396.5 231.195V261.695L429.5 254.195L492.5 273.195H510L523 310.195L556.5 299.195Z" fill="#E9D77A" stroke="black"/>
|
||||
<path d="M586 353.195L609 334.695L619 348.195L628.5 377.695V409.195L616.5 440.695L594.5 472.195L558 502.195L535.5 533.195L526 559.695L504 568.195L437 599.195L390.5 647.695L397 602.695L421.5 536.195L457 493.195L502 448.695L541 401.195L547.5 365.195L586 353.195Z" fill="#FDF7DD" stroke="black"/>
|
||||
<path d="M636.5 274.195L560 296.695V297.195L609.5 331.195L632 383.695L613 450.195L579 481.695L537.5 535.195L526 556.195L560 585.695L570 556.195L628.5 495.195L660 443.195L667.5 363.195L636.5 274.195Z" fill="#19A2F4" stroke="black"/>
|
||||
<path d="M657.5 446.695L736.5 433.695L717 380.195L669 367.695L657.5 446.695Z" fill="url(#paint1_linear_5_2)"/>
|
||||
<path d="M230.5 185.695L298.5 126.195L351.5 154.695L325 181.695L357.5 217.695H385L395 225.195L364.5 233.195L317.5 270.695L270.5 251.195V233.195L257.5 204.195L220.5 199.695L230.5 185.695Z" fill="url(#paint2_linear_5_2)"/>
|
||||
<path d="M200 461.195L297 474.695L313.5 499.195L355 461.195L380 503.695L423.5 463.195L454.5 486.695L416 556.195L386.5 647.195L333.5 590.695V566.695L276.5 556.195L226.5 503.695L219.5 521.195L195 499.195L200 461.195Z" fill="url(#paint3_linear_5_2)"/>
|
||||
<path d="M553.5 581.695L638 487.695L655.5 481.695L688 504.695L716 487.695L732 498.695H752.5L768.5 476.695L790.5 466.195L825 478.695V487.695L724.5 518.695L713 546.695H662.5L641 599.695H575.5L553.5 581.695Z" fill="url(#paint4_linear_5_2)"/>
|
||||
<path d="M848.5 566.695L829.5 484.695L727.5 518.695L713 545.195H661.5L642.5 600.195H576.5L527 559.195L435.5 600.195L385.5 649.195L338 591.695L335 566.695L277.5 556.195L225.5 499.195L218.5 518.195L190 499.195C187.333 511.028 181.8 536.695 181 544.695C180 554.695 163 653.695 169.5 736.695C176 819.695 271 910.695 305.5 925.195C340 939.695 474 985.195 646 951.195C783.6 923.995 838.333 780.195 848.5 711.695V566.695Z" fill="url(#paint5_radial_5_2)"/>
|
||||
<path d="M571 77.1947C463.861 37.8394 340.581 83.6949 294 121.695L352.5 151.195L325 181.695L358 217.195L396 217.195L396 258.695L462.5 244.695L485.5 270.195L508.5 276.195L523 309.695L643 270.195L675.5 364.695L714 382.695L738.5 431.695L754 438.269C776.5 364.695 769.5 390.695 776.5 336.433C773.5 273.195 764.226 234.29 745 211.195C725.774 188.1 704.923 126.389 571 77.1947Z" fill="url(#paint6_radial_5_2)"/>
|
||||
<path d="M510 439.695C492.5 440.361 450.1 438.395 420.5 425.195" stroke="black" stroke-width="16"/>
|
||||
<path d="M547 377.195C563.333 390.695 602.6 413.195 629 395.195" stroke="black" stroke-width="10"/>
|
||||
<path d="M524.5 430.195C526.5 446.528 541.7 478.795 586.5 477.195" stroke="black" stroke-width="10"/>
|
||||
<path d="M471 477.195C475.348 491.921 495.835 521.939 543 524.195" stroke="black" stroke-width="10"/>
|
||||
<path d="M417.5 556.195C427.667 566.361 456.1 584.595 488.5 576.195" stroke="black" stroke-width="10"/>
|
||||
<path d="M552.5 298.695C610.5 316.695 637 364.695 628.5 406.195C611.673 488.349 562.5 470.695 524.5 557.695" stroke="black" stroke-width="10"/>
|
||||
<path d="M168 416.195C281 469.695 341.333 419.028 366 388.695L332.5 381.195C310.5 427.995 214.167 424.028 168 416.195Z" fill="#E356E9"/>
|
||||
<path d="M366 388.695L369.879 391.849L374.977 385.581L367.092 383.816L366 388.695ZM168 416.195L168.836 411.265C166.374 410.847 163.981 412.311 163.231 414.693C162.481 417.075 163.603 419.645 165.86 420.714L168 416.195ZM332.5 381.195L333.592 376.316L329.68 375.44L327.975 379.068L332.5 381.195ZM362.121 385.54C350.162 400.246 329.689 419.713 298.677 429.097C267.772 438.448 225.721 437.991 170.14 411.676L165.86 420.714C223.279 447.899 267.895 448.858 301.573 438.668C335.144 428.51 357.171 407.477 369.879 391.849L362.121 385.54ZM167.164 421.124C190.562 425.094 226.689 428.099 259.903 424.147C276.512 422.171 292.64 418.428 306.149 412.027C319.678 405.617 330.883 396.387 337.025 383.322L327.975 379.068C323.117 389.403 314.031 397.227 301.867 402.99C289.683 408.763 274.717 412.314 258.722 414.217C226.728 418.024 191.605 415.128 168.836 411.265L167.164 421.124ZM367.092 383.816L333.592 376.316L331.408 386.074L364.908 393.574L367.092 383.816Z" fill="black"/>
|
||||
<path d="M388 645.195C393.333 607.861 417 525.595 459 487.195C511.5 439.195 547 411.195 549.5 367.695C533.833 370.361 508.227 383.217 485 396.695C444.5 420.195 394 428.695 388.5 428.695C390.5 419.361 398.4 396.795 396 391.195C393 384.195 321 390.195 294 361.695L285.5 303.195C286.333 299.361 291.2 288.095 296 285.695C298.632 284.379 324.871 269.582 337 257.195C360.5 233.195 374.547 230.695 396 230.695" stroke="black" stroke-width="16"/>
|
||||
<path d="M446 375.195C420.5 388.695 399.667 379.861 387.5 380.195L400 404.695C409 405.195 431.46 403.67 445 396.695C461.5 388.195 487.5 358.195 497.5 350.195C505.5 343.795 521 334.861 527.5 331.195C520 331.195 515.4 331.395 511 332.195C505.5 333.195 483.5 351.195 481 353.695C478.5 356.195 458.577 368.537 446 375.195Z" fill="black"/>
|
||||
<path d="M298.5 127.695L353 152.695L324 180.695L358 218.695H396.5V262.195L463 247.195L484.5 271.195L508.5 276.195L522 308.695L640.5 271.195L676 372.695L715 380.695L739 435.695" stroke="black" stroke-width="10"/>
|
||||
<path d="M313.5 273.695L310 266.695L299 268.195L296 256.195L272 254.695V228.195C272 228.195 261 210.195 255.5 204.195C251.1 199.395 225.333 202.195 213 204.195C251 156.028 350.5 53.6361 501.5 67.6948C646.5 81.1948 839 204.195 754 438.195L734.5 433.695L716.5 441.195L707 433.695L661 441.195" stroke="black" stroke-width="16"/>
|
||||
<path d="M632.5 483.695L657.5 480.695L686 504.695L717 485.195L730 499.195H755.5L766.5 476.195L791 466.695L824.5 476.195C824.5 476.195 985.5 987.336 491 966.195C11.4999 945.695 205 466.695 205 466.695L231 459.695L301 476.195L314 499.195L356 459.695L381.5 504.695L424 464.695L455 489.195" stroke="black" stroke-width="16"/>
|
||||
<path d="M827 484.695L724.5 520.695L712.5 546.195H661.5L641.5 600.195H576L529 557.695L435.5 600.195L385 652.195L335.5 591.195V566.695L277 557.695L226.5 500.195L219.5 520.695L199.5 500.195" stroke="black" stroke-width="10"/>
|
||||
<path d="M631 275.695C653.833 304.195 687.2 389.295 654 451.695C612.5 529.695 569.5 546.195 556 582.695" stroke="black" stroke-width="16"/>
|
||||
<path d="M326.5 301.195V285.695C320 285.195 312 291.195 309 294.195C306 297.195 308.5 306.195 311 308.695C313 310.695 316.167 309.528 317.5 308.695L326.5 301.195Z" fill="black"/>
|
||||
<path d="M353.482 303.385L367.808 297.468C370.752 303.285 368.26 312.97 366.632 316.888C365.005 320.806 355.732 321.931 352.467 320.574C349.855 319.489 349.725 316.117 349.986 314.566L353.482 303.385Z" fill="black"/>
|
||||
<path d="M552 364.195C571 361.695 598.691 349.657 606.5 335.695" stroke="black" stroke-width="10"/>
|
||||
<path d="M442.67 349.364C466.788 355.842 492.259 339.056 499.559 311.873C503.314 297.893 501.532 283.885 495.635 272.695L486 270.695L462 247.695L444 252.165C429.317 257.545 416.952 270.796 412.219 288.415C404.919 315.599 418.552 342.886 442.67 349.364Z" fill="black"/>
|
||||
<path d="M458.438 268.743C460.823 266.79 464.898 265.325 469.371 266.79C474.478 268.463 481.05 272.649 483.783 278.02C487.262 284.856 487.262 292.668 486.765 302.433C486.342 310.738 480.867 332.561 462.5 334.195C445.102 335.742 444.306 318.104 445 303.195C446 281.695 453.667 272.649 458.438 268.743Z" fill="#FECD10"/>
|
||||
<path d="M446.814 272.167C446.593 271.194 446.029 269.422 444.314 268.167C442.783 267.047 440.814 266.667 438.814 266.667C436.314 266.667 435.346 267.238 433.689 268.922C432.279 270.353 429.963 274.617 432.667 280.492C435.301 286.214 438.775 284.645 442.542 281.619C446.217 278.666 447.257 274.113 446.814 272.167Z" fill="white"/>
|
||||
<mask id="mask0_5_2" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="444" y="266" width="43" height="69">
|
||||
<path d="M458.438 268.743C460.823 266.79 464.898 265.325 469.371 266.79C474.478 268.463 481.05 272.649 483.783 278.02C487.262 284.856 487.262 292.668 486.765 302.433C486.342 310.738 480.867 332.561 462.5 334.195C445.102 335.742 444.306 318.104 445 303.195C446 281.695 453.667 272.649 458.438 268.743Z" fill="#FE9F10"/>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8.55943 6.31327L8.64596 5.74805L7.74914 6.10704L6.74219 6.55005L7.00966 6.73336L8.00088 6.83266L8.55943 6.31327Z" fill="url(#paint0_linear_19481_12925)"/>
|
||||
<path d="M8.76377 4.67867L9.58192 5.19043L9.30658 5.47304L8.76377 5.66399L8.3547 5.87785L7.73322 6.12227L6.92293 6.46599L6.15198 6.64166L6.30145 6.08408L4.99556 5.87785L4.63368 5.57233L4.50781 4.67867L4.72022 4.48008L5.38103 3.93778L5.76651 3.69336L6.24638 3.63989V4.10582L6.76559 3.99124L7.75682 4.28149H8.03216L8.23669 4.84671L8.76377 4.67867Z" fill="#E9D77A"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.2538 3.63159V4.09651L6.76542 3.98361L7.75752 4.27412H8.03728L8.24111 4.83738L8.76443 4.67054L9.5937 5.18925L9.31056 5.47986L8.76654 5.67124L8.35759 5.88504L7.73591 6.12954L7.73572 6.12962L6.92497 6.47353L6.14063 6.65226L6.29121 6.09054L4.99163 5.88531L4.62584 5.57647L4.49902 4.67613L4.71449 4.47467L5.37587 3.9319L5.76331 3.68624L6.2538 3.63159ZM5.7688 3.70101L5.38529 3.94418L4.72504 4.48602L4.5157 4.68175L4.64062 5.56871L4.99858 5.87093L6.31079 6.07815L6.16243 6.6316L6.91998 6.45897L7.72981 6.11546L8.35089 5.8712L8.7601 5.65726L9.3017 5.46673L9.56924 5.19213L8.76221 4.68733L8.23137 4.85657L8.02613 4.28939H7.7552L6.76486 3.9994L6.23806 4.11565V3.64872L5.7688 3.70101Z" fill="black"/>
|
||||
<path d="M9.2273 5.50362L9.58917 5.22101L9.74651 5.42724L9.89598 5.87788V6.35908L9.70718 6.84028L9.36104 7.32148L8.78676 7.77977L8.43275 8.25333L8.28328 8.65815L7.93714 8.788L6.88298 9.26156L6.15137 10.0025L6.25364 9.31503L6.63911 8.29916L7.19766 7.64228L7.90567 6.96249L8.51929 6.23687L8.62155 5.68693L9.2273 5.50362Z" fill="#FDF7DD"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.59117 5.21027L9.75415 5.42389L9.9044 5.87688V6.36068L9.71473 6.84408L9.36742 7.32691L8.79308 7.78524L8.44033 8.25713L8.29002 8.66421L7.94076 8.79523L6.88818 9.26808L6.14062 10.0251L6.24652 9.31333L6.63274 8.29549L7.19239 7.63732L7.9004 6.95753L8.51246 6.23375L8.61521 5.68121L9.22408 5.49695L9.59117 5.21027ZM9.58828 5.23213L9.23162 5.51067L8.629 5.69304L8.52721 6.24038L7.91204 6.96784L7.20402 7.64764L6.64658 8.30321L6.26185 9.31711L6.16321 9.98018L6.87888 9.25543L7.93462 8.78115L8.27764 8.65248L8.42627 8.24992L8.78153 7.77468L9.35576 7.31644L9.70072 6.83688L9.88866 6.35787V5.87928L9.73997 5.43097L9.58828 5.23213Z" fill="black"/>
|
||||
<path d="M10.0218 4.29681L8.81815 4.64053V4.64817L9.59696 5.16756L9.95097 5.96956L9.65203 6.98542L9.11709 7.46662L8.46414 8.2839L8.2832 8.6047L8.81815 9.05535L8.97548 8.6047L9.8959 7.67285L10.3915 6.87849L10.5095 5.65639L10.0218 4.29681Z" fill="#19A2F4"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.0269 4.28748L10.5177 5.65549L10.3994 6.88099L9.90236 7.67757L8.98255 8.6088L8.82202 9.06861L8.27344 8.60647L8.45772 8.27974L9.11145 7.46149L9.64525 6.98131L9.94282 5.97011L9.59081 5.17264L8.81046 4.65223V4.63485L10.0269 4.28748ZM8.8284 4.64566L9.60348 5.16256L9.95949 5.96909L9.65917 6.98962L9.12309 7.47184L8.47092 8.28814L8.29333 8.60301L8.81464 9.04217L8.96878 8.60068L9.88981 7.66822L10.384 6.87607L10.5017 5.65738L10.017 4.30623L8.8284 4.64566Z" fill="black"/>
|
||||
<path d="M10.3525 6.93192L11.5955 6.73333L11.2887 5.91605L10.5335 5.7251L10.3525 6.93192Z" fill="url(#paint1_linear_19481_12925)"/>
|
||||
<path d="M3.6339 2.94482L4.70379 2.03589L5.53767 2.47126L5.12073 2.88372L5.63208 3.43366H6.06475L6.22209 3.54823L5.74221 3.67044L5.00273 4.2433L4.26325 3.94541V3.67044L4.05871 3.22743L3.47656 3.15869L3.6339 2.94482Z" fill="url(#paint2_linear_19481_12925)"/>
|
||||
<path d="M3.15484 7.15344L4.68101 7.35967L4.94061 7.73394L5.59356 7.15344L5.9869 7.80268L6.67132 7.18399L7.15906 7.54299L6.55331 8.60468L6.08917 9.99481L5.25529 9.13171V8.76508L4.35847 8.60468L3.57178 7.80268L3.46165 8.07001L3.07617 7.73394L3.15484 7.15344Z" fill="url(#paint3_linear_19481_12925)"/>
|
||||
<path d="M8.7168 8.9942L10.0463 7.55824L10.3216 7.46658L10.833 7.81793L11.2735 7.55824L11.5253 7.72627H11.8478L12.0995 7.3902L12.4457 7.2298L12.9885 7.42075V7.55824L11.4073 8.0318L11.2263 8.45953H10.4318L10.0935 9.26917H9.06294L8.7168 8.9942Z" fill="url(#paint4_linear_19481_12925)"/>
|
||||
<path d="M13.3578 8.7651L13.0588 7.51245L11.454 8.03184L11.2259 8.43666H10.4156L10.1166 9.27685H9.07821L8.29939 8.65053L6.85976 9.27685L6.07308 10.0254L5.32573 9.147L5.27853 8.7651L4.37384 8.6047L3.55569 7.73396L3.44556 8.0242L2.99715 7.73396C2.95518 7.91472 2.86813 8.30681 2.85554 8.42902C2.83981 8.58178 2.57234 10.0941 2.67461 11.3621C2.77687 12.63 4.27157 14.0201 4.81439 14.2416C5.3572 14.4631 7.46551 15.1582 10.1717 14.6388C12.3367 14.2233 13.1978 12.0266 13.3578 10.9801V8.7651Z" fill="url(#paint5_radial_19481_12925)"/>
|
||||
<path d="M8.99202 1.28759C7.30633 0.68639 5.36668 1.38689 4.63379 1.96738L5.55421 2.41803L5.12153 2.88395L5.64074 3.42626H6.23862V4.06022L7.28491 3.84635L7.64679 4.2359L8.00866 4.32755L8.2368 4.83931L10.1248 4.2359L10.6362 5.6795L11.2419 5.95447L11.6274 6.703L11.8713 6.80343C12.2253 5.6795 12.1152 6.07668 12.2253 5.24776C12.1781 4.28173 12.0322 3.68741 11.7297 3.3346C11.4272 2.9818 11.0991 2.03909 8.99202 1.28759Z" fill="url(#paint6_radial_19481_12925)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.67479 6.492C7.11394 6.68214 7.75775 6.71295 8.02691 6.703L8.03648 6.94724C7.75496 6.95765 7.06456 6.92838 6.57227 6.71523L6.67479 6.492Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.17436 6.26078C8.92463 6.1798 8.69757 6.03688 8.56348 5.92927L8.66371 5.81152C8.7866 5.91014 8.99693 6.04219 9.2242 6.11589C9.45299 6.19007 9.68154 6.20003 9.85944 6.08226L9.94807 6.20848C9.7106 6.36568 9.42256 6.34126 9.17436 6.26078Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.43859 7.19513C8.27321 7.03027 8.19918 6.82847 8.18164 6.6894L8.33781 6.67084C8.35174 6.78127 8.41302 6.95069 8.5513 7.08855C8.68715 7.22398 8.90144 7.33325 9.23241 7.32177L9.23802 7.47443C8.86412 7.4874 8.6064 7.36243 8.43859 7.19513Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.54729 8.19231C7.76816 8.15612 7.4196 7.67229 7.34277 7.41966L7.49367 7.3764C7.55366 7.57369 7.84978 8.00698 8.5548 8.03972L8.54729 8.19231Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.71297 8.98419C7.16544 9.12202 6.69078 8.82405 6.52051 8.65874L6.63176 8.55072C6.78141 8.69601 7.20147 8.95513 7.67348 8.83632L7.71297 8.98419Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.81883 6.29808C9.9431 5.70898 9.55753 5.00954 8.67682 4.74416L8.72345 4.59827C9.66785 4.88283 10.1162 5.64991 9.97296 6.32873C9.90506 6.65061 9.8036 6.87869 9.67789 7.0602C9.55266 7.24101 9.4057 7.37199 9.25443 7.50033C9.23755 7.51465 9.22057 7.52898 9.2035 7.54338C8.91728 7.78485 8.60678 8.0468 8.33168 8.65832L8.1875 8.59718C8.47684 7.954 8.80913 7.67369 9.09998 7.42834C9.1171 7.4139 9.13408 7.39957 9.1509 7.3853C9.30087 7.25806 9.43435 7.13808 9.54733 6.97496C9.65982 6.81253 9.75435 6.6037 9.81883 6.29808Z" fill="black"/>
|
||||
<path d="M2.65137 6.466C4.42927 7.28328 5.37853 6.50928 5.76663 6.04591L5.23956 5.93134C4.89342 6.64626 3.37774 6.58566 2.65137 6.466Z" fill="#E356E9"/>
|
||||
<path d="M5.76621 6.04599L5.82724 6.09417L5.90745 5.99842L5.78339 5.97146L5.76621 6.04599ZM2.65094 6.46609L2.6641 6.39078C2.62536 6.38439 2.58771 6.40675 2.57591 6.44314C2.56411 6.47953 2.58176 6.51879 2.61727 6.53512L2.65094 6.46609ZM5.23913 5.93142L5.25632 5.85689L5.19476 5.84351L5.16794 5.89893L5.23913 5.93142ZM5.70518 5.9978C5.51702 6.22245 5.19491 6.51983 4.70697 6.66318C4.22072 6.80603 3.55911 6.79905 2.68461 6.39705L2.61727 6.53512C3.52069 6.9504 4.22266 6.96505 4.75254 6.80939C5.28073 6.65421 5.6273 6.33291 5.82724 6.09417L5.70518 5.9978ZM2.63779 6.54138C3.00593 6.60203 3.57434 6.64793 4.09692 6.58756C4.35824 6.55738 4.61199 6.5002 4.82454 6.40242C5.0374 6.3045 5.21369 6.1635 5.31033 5.96391L5.16794 5.89893C5.0915 6.05681 4.94855 6.17633 4.75716 6.26436C4.56547 6.35255 4.32999 6.4068 4.07833 6.43587C3.57495 6.49403 3.02234 6.44979 2.6641 6.39078L2.63779 6.54138ZM5.78339 5.97146L5.25632 5.85689L5.22195 6.00595L5.74903 6.12052L5.78339 5.97146Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.83286 3.81079C5.71165 3.85751 5.57829 3.94594 5.40013 4.1226C5.29415 4.22768 5.13296 4.33768 4.99976 4.42096C4.86887 4.50279 4.75369 4.56575 4.72358 4.58071C4.72319 4.58113 4.71779 4.58521 4.70818 4.59707C4.69617 4.61188 4.68303 4.63205 4.67013 4.65551C4.6503 4.69154 4.63587 4.72631 4.62832 4.74797L4.75213 5.57529C4.83736 5.65125 4.95582 5.71065 5.09702 5.75665C5.25282 5.80741 5.42681 5.83885 5.59451 5.86084C5.70409 5.87521 5.80514 5.88494 5.89696 5.89378C5.94816 5.89871 5.99649 5.90336 6.04183 5.90839C6.10183 5.91504 6.15849 5.92261 6.20314 5.93315C6.22518 5.93836 6.25029 5.94563 6.2734 5.95679C6.29293 5.96622 6.33337 5.98885 6.35417 6.03597C6.36858 6.0686 6.3712 6.10232 6.37141 6.12642C6.37163 6.15264 6.36892 6.18026 6.36501 6.20689C6.35719 6.26019 6.34284 6.32091 6.32736 6.3795C6.31517 6.42568 6.30279 6.46914 6.29122 6.50913C6.38338 6.4919 6.50357 6.46576 6.63969 6.42935C6.92294 6.35358 7.26969 6.23477 7.57561 6.06242C7.76032 5.95835 7.95595 5.85585 8.13776 5.77385C8.31719 5.69293 8.49203 5.62785 8.63248 5.60464L8.78833 5.57889L8.77926 5.73213C8.75746 6.10049 8.59044 6.39813 8.33236 6.69147C8.12435 6.92789 7.84893 7.17019 7.53236 7.44868C7.46174 7.51081 7.38906 7.57474 7.31463 7.64082C7.00527 7.91544 6.75558 8.35577 6.57192 8.80835C6.38917 9.25868 6.27772 9.70622 6.23721 9.98154L5.98801 9.94698C6.03141 9.65198 6.14809 9.186 6.33771 8.71875C6.52641 8.25374 6.79332 7.77241 7.14477 7.46043C7.22215 7.39174 7.29675 7.32609 7.36848 7.26295C7.68423 6.98507 7.94441 6.75611 8.14095 6.53271C8.33083 6.3169 8.45322 6.11482 8.50364 5.89115C8.42644 5.91731 8.33884 5.95267 8.24382 5.99552C8.07121 6.07337 7.88268 6.17201 7.70195 6.27383C7.37065 6.46047 7.00152 6.58609 6.70655 6.66499C6.55858 6.70457 6.42789 6.73276 6.32805 6.75114C6.23308 6.76862 6.15579 6.77918 6.12048 6.77918H5.96478L5.9974 6.63136C6.00677 6.5889 6.02539 6.52422 6.04466 6.4573C6.0583 6.4099 6.07227 6.36136 6.08351 6.3188C6.09833 6.26269 6.10994 6.21227 6.11579 6.17242C6.11615 6.16993 6.11649 6.16753 6.11679 6.16521C6.09051 6.16055 6.0562 6.15599 6.01327 6.15123C5.97487 6.14697 5.92987 6.14262 5.88043 6.13784C5.7853 6.12865 5.67369 6.11786 5.56082 6.10306C5.38631 6.08018 5.19449 6.04622 5.01694 5.98837C4.84044 5.93087 4.66833 5.8467 4.54227 5.71751L4.51482 5.68938L4.37207 4.73548L4.37691 4.71386C4.38677 4.66979 4.41463 4.60115 4.44808 4.54034C4.4654 4.50886 4.48638 4.47548 4.51038 4.44588C4.53279 4.41824 4.5655 4.38419 4.60882 4.36316C4.62394 4.35583 4.7333 4.29684 4.86347 4.21546C4.99475 4.13338 5.1354 4.03574 5.22026 3.9516C5.41184 3.76163 5.57386 3.64765 5.73997 3.58362C5.90645 3.51945 6.06567 3.51007 6.23848 3.51007V3.75449C6.07375 3.75449 5.9537 3.76421 5.83286 3.81079ZM6.1193 6.12149C6.1193 6.12149 6.11932 6.1216 6.11935 6.12183C6.11931 6.12161 6.11929 6.1215 6.1193 6.12149Z" fill="black"/>
|
||||
<path d="M7.02491 5.83969C6.6237 6.04592 6.29592 5.91097 6.10449 5.91607L6.30116 6.29034C6.44277 6.29798 6.79614 6.27468 7.00918 6.16813C7.26878 6.03828 7.67786 5.58 7.8352 5.45779C7.96107 5.36002 8.20494 5.22354 8.30721 5.16754C8.1892 5.16754 8.11683 5.1706 8.0476 5.18282C7.96107 5.19809 7.61492 5.47307 7.57559 5.51126C7.53626 5.54945 7.22279 5.73798 7.02491 5.83969Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.42461 2.46373L4.67188 2.12847L4.73748 1.98962L5.69971 2.41818L5.21501 2.87256L5.676 3.3728H6.32524V4.01817L7.32063 3.80017L7.67249 4.18153L8.06546 4.26101L8.26615 4.7301L10.1346 4.156L10.7037 5.7356L11.3135 5.85706L11.7075 6.73357L11.5633 6.79466L11.202 5.99079L10.5846 5.86783L10.0365 4.34637L8.17616 4.91798L7.95203 4.39411L7.58979 4.32084L7.2651 3.96893L6.16791 4.20923V3.52556H5.60566L4.99676 2.86482L5.42461 2.46373Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.65651 3.07077C3.68279 3.06895 3.70901 3.06748 3.73476 3.06645C3.80471 3.06367 3.87549 3.064 3.93582 3.07092C3.96591 3.07437 3.99723 3.07987 4.0262 3.08914C4.05308 3.09774 4.09053 3.11346 4.12024 3.14493C4.17162 3.19936 4.24199 3.29964 4.29501 3.37825C4.32262 3.4192 4.34742 3.45714 4.3653 3.48481C4.37425 3.49867 4.38149 3.50999 4.38651 3.51788C4.38805 3.52029 4.38937 3.52238 4.39048 3.52412C4.39119 3.52524 4.39181 3.52622 4.39233 3.52705L4.39388 3.5295L4.39441 3.53034L4.39444 3.53039L4.39445 3.53041C4.39446 3.53041 4.39446 3.53042 4.28706 3.59414L4.39445 3.53041L4.41293 3.55976V3.88415L4.76444 3.90548L4.80662 4.0693L4.95722 4.04937L5.05259 4.23456L4.82742 4.34386L4.81266 4.31519L4.61711 4.34108L4.56489 4.13827L4.16119 4.11377V3.6289C4.1584 3.62456 4.15534 3.6198 4.15203 3.61468C4.13475 3.58793 4.11087 3.5514 4.0844 3.51214C4.0338 3.43712 3.97961 3.36103 3.94386 3.32023C3.93617 3.31812 3.92395 3.31567 3.90629 3.31365C3.86507 3.30892 3.80938 3.30811 3.74508 3.31067C3.61735 3.31575 3.47273 3.33338 3.37892 3.34815L3.05957 3.39843L3.25995 3.15182C3.8646 2.40769 5.46728 0.799849 7.9096 1.02063C9.07549 1.12602 10.4346 1.65795 11.3348 2.62724C12.2422 3.60421 12.6731 5.01544 11.989 6.84387L11.951 6.94555L11.575 6.86131L11.2608 6.98842L11.0967 6.86268L10.4277 6.96859L10.3872 6.72735L11.1657 6.60412L11.3006 6.70752L11.5528 6.60549L11.7895 6.65852C12.3893 4.96295 11.9744 3.6809 11.1479 2.79092C10.2977 1.8755 9.00176 1.36483 7.88627 1.26399C5.80161 1.07555 4.35336 2.29633 3.65651 3.07077ZM3.95112 3.32266C3.9511 3.32267 3.95075 3.32253 3.95013 3.32222C3.95083 3.3225 3.95114 3.32265 3.95112 3.32266Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.63945 6.93506L6.04062 7.62244L6.67166 7.04579L7.24462 7.48544L7.08853 7.67721L6.686 7.36833L5.97968 8.01378L5.57844 7.3263L4.91749 7.92983L4.66111 7.48942L3.64428 7.2567L3.32761 7.33948C3.32491 7.34646 3.32199 7.35406 3.31885 7.36228C3.29886 7.41474 3.27032 7.49217 3.23655 7.59109C3.169 7.78897 3.08063 8.07251 2.99786 8.41384C2.83202 9.09773 2.69008 10.0078 2.77927 10.9239C2.86838 11.8392 3.18717 12.7522 3.93476 13.456C4.68196 14.1594 5.87333 14.6686 7.73836 14.746C9.66236 14.8258 10.9291 14.4025 11.755 13.7405C12.5814 13.0781 12.9838 12.1629 13.1502 11.2258C13.3166 10.2879 13.2448 9.33637 13.13 8.61643C13.0727 8.25709 13.005 7.95691 12.9516 7.74688C12.9249 7.64189 12.9019 7.55952 12.8856 7.50364C12.8834 7.49591 12.8812 7.48868 12.8792 7.48197L12.4593 7.36635L12.1596 7.47916L11.9739 7.8563H11.4384L11.2675 7.67759L10.7903 7.96906L10.3134 7.57914L9.9743 7.61865L9.94431 7.37597L10.3919 7.32382L10.8118 7.66715L11.3101 7.36286L11.5482 7.61188H11.8152L11.9756 7.2863L12.4469 7.10887L13.0798 7.28315L13.1002 7.34602L12.9802 7.38273C13.1002 7.34602 13.1002 7.3461 13.1003 7.34621L13.1004 7.34657L13.1008 7.34784C13.1012 7.34892 13.1017 7.35047 13.1023 7.35248C13.1036 7.35651 13.1054 7.36239 13.1078 7.37005C13.1125 7.38539 13.1193 7.40788 13.1278 7.43705C13.1448 7.49539 13.1686 7.58046 13.196 7.68836C13.2508 7.90408 13.3202 8.2114 13.3788 8.57904C13.4958 9.31306 13.571 10.2935 13.3982 11.2673C13.2253 12.2418 12.8022 13.2181 11.9153 13.929C11.028 14.6402 9.69377 15.0718 7.72761 14.9902C5.8205 14.911 4.56332 14.3881 3.75952 13.6314C2.95611 12.8751 2.62146 11.9001 2.52865 10.9469C2.43592 9.9945 2.58358 9.05572 2.75282 8.35782C2.83759 8.00827 2.92813 7.71769 2.9976 7.51419C3.03234 7.41241 3.06185 7.33233 3.08276 7.27745C3.09322 7.25001 3.10154 7.22886 3.10729 7.21445C3.11017 7.20724 3.1124 7.20172 3.11395 7.19793C3.11472 7.19604 3.11532 7.19458 3.11574 7.19356L3.11623 7.19237L3.11638 7.19202C3.11642 7.19191 3.11645 7.19184 3.23316 7.23761L3.11645 7.19184L3.13992 7.13542L3.64019 7.00465L4.82607 7.27605L4.97876 7.53835L5.63945 6.93506Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.993 7.44061L13.0451 7.58474L11.4635 8.12409L11.2675 8.52854H10.4699L10.1552 9.35346H9.03959L8.31594 8.71812L6.90538 9.34064L6.05948 10.1863L5.20726 9.16668V8.83085L4.32528 8.69911L3.60151 7.89897L3.49391 8.20492L3.08984 7.8028L3.20246 7.69612L3.42774 7.92032L3.54042 7.59994L4.40575 8.55657L5.3646 8.6998V9.1125L6.07002 9.95653L6.81322 9.21351L8.34486 8.53756L9.10018 9.2007H10.0457L10.3604 8.37578H11.1676L11.3492 8.00116L12.993 7.44061Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.3243 5.49565C10.2167 5.01183 10.0027 4.59634 9.83754 4.39617L10.034 4.24335C10.2281 4.47855 10.4562 4.93075 10.5703 5.44408C10.6846 5.95799 10.6892 6.55404 10.4088 7.06577C10.0747 7.67533 9.7338 8.04541 9.45248 8.33114C9.42221 8.36188 9.39294 8.3914 9.36468 8.41988C9.12527 8.66127 8.95862 8.82929 8.8738 9.05194L8.6377 8.96715C8.74202 8.6933 8.9485 8.48596 9.18083 8.25265C9.21036 8.223 9.2403 8.19293 9.27051 8.16225C9.54381 7.88466 9.86761 7.53295 10.1865 6.95096C10.4285 6.50946 10.4317 5.97889 10.3243 5.49565Z" fill="black"/>
|
||||
<path d="M5.14457 4.70946V4.47268C5.0423 4.46504 4.91643 4.5567 4.86923 4.60253C4.82203 4.64835 4.86136 4.78584 4.90069 4.82403C4.93216 4.85458 4.98199 4.83676 5.00296 4.82403L5.14457 4.70946Z" fill="black"/>
|
||||
<path d="M5.56917 4.74286L5.79457 4.65247C5.84089 4.74133 5.80168 4.88928 5.77607 4.94913C5.75047 5.00898 5.60457 5.02617 5.5532 5.00544C5.5121 4.98886 5.51006 4.93735 5.51416 4.91366L5.56917 4.74286Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.22245 5.58817C9.05414 5.66877 8.86224 5.7271 8.70314 5.74742L8.68262 5.59596C8.82246 5.5781 8.99787 5.52538 9.15285 5.45116C9.3109 5.37548 9.43233 5.28475 9.48171 5.19904L9.61902 5.2736C9.54554 5.40117 9.38769 5.50904 9.22245 5.58817Z" fill="black"/>
|
||||
<path d="M6.97297 5.44508C7.35244 5.54404 7.75319 5.28762 7.86804 4.87236C7.92712 4.6588 7.89909 4.44481 7.80631 4.27387L7.65471 4.24332L7.2771 3.89197L6.9939 3.96025C6.76288 4.04244 6.56833 4.24486 6.49386 4.51401C6.37901 4.92928 6.59351 5.34612 6.97297 5.44508Z" fill="black"/>
|
||||
<path d="M7.22082 4.21349C7.25835 4.18365 7.32246 4.16127 7.39284 4.18365C7.47319 4.20921 7.57659 4.27316 7.61959 4.3552C7.67433 4.45963 7.67433 4.57897 7.66651 4.72814C7.65985 4.85501 7.57371 5.18838 7.28473 5.21334C7.011 5.23698 6.99847 4.96753 7.00939 4.73978C7.02513 4.41134 7.14576 4.27316 7.22082 4.21349Z" fill="#FECD10"/>
|
||||
<path d="M7.03815 4.26603C7.03468 4.25116 7.0258 4.22409 6.99882 4.20492C6.97473 4.18781 6.94375 4.18201 6.91228 4.18201C6.87295 4.18201 6.85772 4.19073 6.83165 4.21645C6.80946 4.23831 6.77302 4.30345 6.81557 4.3932C6.85701 4.48061 6.91167 4.45664 6.97094 4.41042C7.02876 4.36531 7.04512 4.29575 7.03815 4.26603Z" fill="white"/>
|
||||
<mask id="mask0_19481_12925" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="7" y="4" width="1" height="2">
|
||||
<path d="M7.22082 4.21349C7.25835 4.18365 7.32246 4.16127 7.39284 4.18365C7.47319 4.20921 7.57659 4.27316 7.61959 4.3552C7.67433 4.45963 7.67433 4.57897 7.66651 4.72814C7.65985 4.85501 7.57371 5.18838 7.28473 5.21334C7.011 5.23698 6.99847 4.96753 7.00939 4.73978C7.02513 4.41134 7.14576 4.27316 7.22082 4.21349Z" fill="#FE9F10"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_5_2)">
|
||||
<g filter="url(#filter0_f_5_2)">
|
||||
<path d="M492 309.695L489 276.195L477 265.195L467.5 264.195L460 267.195C483.5 274.695 482.5 310.195 476 328.695L492 309.695Z" fill="#FE9F10"/>
|
||||
<g mask="url(#mask0_19481_12925)">
|
||||
<g filter="url(#filter0_f_19481_12925)">
|
||||
<path d="M7.74859 4.83905L7.70139 4.3273L7.51259 4.15926L7.36312 4.14398L7.24512 4.18981C7.61486 4.30438 7.59912 4.84669 7.49686 5.1293L7.74859 4.83905Z" fill="#FE9F10"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_f_5_2" x="451" y="255.195" width="50" height="82.5" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<filter id="filter0_f_19481_12925" x="-1.75488" y="-4.85602" width="18.5039" height="18.9853" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="4.5" result="effect1_foregroundBlur_5_2"/>
|
||||
<feGaussianBlur stdDeviation="4.5" result="effect1_foregroundBlur_19481_12925"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_5_2" x1="488.5" y1="369.195" x2="488.5" y2="440.195" gradientUnits="userSpaceOnUse">
|
||||
<linearGradient id="paint0_linear_19481_12925" x1="7.69407" y1="5.74805" x2="7.69407" y2="6.83266" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#714D29"/>
|
||||
<stop offset="1" stop-color="#C1A180"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_5_2" x1="697" y1="367.695" x2="697" y2="446.695" gradientUnits="userSpaceOnUse">
|
||||
<linearGradient id="paint1_linear_19481_12925" x1="10.974" y1="5.7251" x2="10.974" y2="6.93192" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#714D29"/>
|
||||
<stop offset="1" stop-color="#C1A180"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_5_2" x1="307.75" y1="126.195" x2="307.75" y2="270.695" gradientUnits="userSpaceOnUse">
|
||||
<linearGradient id="paint2_linear_19481_12925" x1="4.84933" y1="2.03589" x2="4.84933" y2="4.2433" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#714D29"/>
|
||||
<stop offset="1" stop-color="#C1A180"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_5_2" x1="324.75" y1="461.195" x2="324.75" y2="647.195" gradientUnits="userSpaceOnUse">
|
||||
<linearGradient id="paint3_linear_19481_12925" x1="5.11762" y1="7.15344" x2="5.11762" y2="9.99481" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#C1A180"/>
|
||||
<stop offset="1" stop-color="#714D29"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint4_linear_5_2" x1="689.25" y1="466.195" x2="689.25" y2="599.695" gradientUnits="userSpaceOnUse">
|
||||
<linearGradient id="paint4_linear_19481_12925" x1="10.8526" y1="7.2298" x2="10.8526" y2="9.26917" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#C1A180"/>
|
||||
<stop offset="1" stop-color="#714D29"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="paint5_radial_5_2" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(283.5 642.695) rotate(17.4274) scale(512.526 728.349)">
|
||||
<radialGradient id="paint5_radial_19481_12925" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(4.46824 9.92609) rotate(16.9501) scale(8.04316 11.1551)">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="#BBBBBB"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="paint6_radial_5_2" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(436.5 102.195) rotate(30.5854) scale(363.585 350.906)">
|
||||
<radialGradient id="paint6_radial_19481_12925" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(6.87584 1.6695) rotate(29.8502) scale(5.67793 5.40072)">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="#C0C0C0"/>
|
||||
</radialGradient>
|
||||
|
||||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 21 KiB |
@@ -1,2 +1,6 @@
|
||||
python.hatch.error.executable.is.not.found=Hatch executable is not found at: {0}
|
||||
python.hatch.error.base.python.executable.is.not.found=Base python executable is not found at: {0}
|
||||
python.hatch.error.working.directory.is.not.found=Working directory is not found at: {0}
|
||||
python.hatch.error.environment.creation=Environment creation failure: {0}
|
||||
python.hatch.error.filesystem.operation=The problem with the filesystem operation: {0}
|
||||
python.hatch.cli.error.response.out.of.pattern=Hatch command responded with non-expected output.\nExpected: {0}
|
||||
|
||||
@@ -4,7 +4,9 @@ import com.intellij.ide.util.PropertiesComponent
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import com.intellij.platform.eel.LocalEelApi
|
||||
import com.intellij.platform.eel.provider.asNioPath
|
||||
import com.intellij.platform.eel.provider.localEel
|
||||
import com.intellij.platform.eel.provider.utils.where
|
||||
import com.intellij.python.hatch.runtime.getHatchCommand
|
||||
import com.jetbrains.python.Result
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.isExecutable
|
||||
@@ -16,22 +18,22 @@ object HatchConfiguration {
|
||||
get() = PropertiesComponent.getInstance().getValue(PYCHARM_HATCH_LOCAL_EXECUTABLE_PATH_SETTING)?.let { Path.of(it) }
|
||||
set(value) = PropertiesComponent.getInstance().setValue(PYCHARM_HATCH_LOCAL_EXECUTABLE_PATH_SETTING, value?.toString())
|
||||
|
||||
fun getPersistedPathForTarget(eelApi: EelApi): Path? = when {
|
||||
fun getPersistedPathForTarget(eelApi: EelApi = localEel): Path? = when {
|
||||
eelApi is LocalEelApi -> localHatchExecutablePath
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun persistPathForTarget(eelApi: EelApi, hatchExecutablePath: Path?) {
|
||||
fun persistPathForTarget(eelApi: EelApi = localEel, hatchExecutablePath: Path?) {
|
||||
if (eelApi is LocalEelApi) localHatchExecutablePath = hatchExecutablePath
|
||||
}
|
||||
|
||||
suspend fun getOrDetectHatchExecutablePath(eelApi: EelApi): Result<Path, HatchError> {
|
||||
suspend fun getOrDetectHatchExecutablePath(eelApi: EelApi = localEel): Result<Path, HatchError> {
|
||||
val path = getPersistedPathForTarget(eelApi) ?: run {
|
||||
detectHatchExecutable(eelApi)?.also { persistPathForTarget(eelApi, it) }
|
||||
}
|
||||
|
||||
val result = when {
|
||||
path?.isExecutable() != true -> Result.failure(ExecutableNotFoundHatchError(path))
|
||||
path?.isExecutable() != true -> Result.failure(HatchExecutableNotFoundHatchError(path))
|
||||
else -> Result.success(path)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.python.hatch
|
||||
|
||||
import com.intellij.python.community.execService.ExecOptions
|
||||
import com.intellij.python.community.execService.ExecService
|
||||
import com.intellij.python.community.execService.WhatToExec
|
||||
import com.intellij.python.community.execService.ProcessOutputTransformer
|
||||
import com.intellij.python.hatch.cli.HatchCli
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError.ExecException
|
||||
import java.nio.file.Path
|
||||
|
||||
|
||||
class HatchRuntime(
|
||||
val hatchBinary: WhatToExec,
|
||||
val execOptions: ExecOptions,
|
||||
private val execService: ExecService = ExecService(),
|
||||
) {
|
||||
fun hatchCli(): HatchCli = HatchCli(this)
|
||||
|
||||
fun withWorkingDirectory(workDirectoryPath: Path): HatchRuntime {
|
||||
val execOptions = with(this.execOptions) {
|
||||
ExecOptions(env, workDirectoryPath, processDescription, timeout)
|
||||
}
|
||||
return HatchRuntime(this.hatchBinary, execOptions)
|
||||
}
|
||||
|
||||
fun withBasePythonPath(basePythonPath: Path): HatchRuntime {
|
||||
val execOptions = with(this.execOptions) {
|
||||
val modifiedEnv = env + mapOf(
|
||||
HatchConstants.AppEnvVars.PYTHON to basePythonPath.toString()
|
||||
)
|
||||
ExecOptions(modifiedEnv, workingDirectory, processDescription, timeout)
|
||||
}
|
||||
return HatchRuntime(this.hatchBinary, execOptions)
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure execution of [hatchBinary] with command line [arguments] and [execOptions] by [execService]
|
||||
* Doesn't make any validation of stdout/stderr content.
|
||||
*/
|
||||
internal suspend fun <T> execute(vararg arguments: String, processOutputTransformer: ProcessOutputTransformer<T>): Result<T, ExecException> {
|
||||
return execService.execute(hatchBinary, arguments.toList(), execOptions, processOutputTransformer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ package com.intellij.python.hatch.cli
|
||||
|
||||
import com.intellij.execution.process.ProcessOutput
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.platform.eel.provider.utils.sendWholeText
|
||||
import com.intellij.python.community.execService.ProcessOutputTransformer
|
||||
import com.intellij.python.community.execService.ZeroCodeStdoutTransformer
|
||||
import com.intellij.python.hatch.HatchRuntime
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.intellij.python.hatch.PyHatchBundle
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError
|
||||
@@ -110,9 +110,21 @@ class HatchCli(private val runtime: HatchRuntime) {
|
||||
* ├── LICENSE.txt
|
||||
* ├── README.md
|
||||
* └── pyproject.toml
|
||||
*
|
||||
* @param[initExistingProject] Initialize an existing project
|
||||
*/
|
||||
suspend fun new(projectName: String): Result<String, PyError> {
|
||||
return runtime.executeAndHandleErrors("new", projectName, transformer = ZeroCodeStdoutTransformer)
|
||||
suspend fun new(projectName: String, location: Path? = null, initExistingProject: Boolean = false): Result<String, PyError> {
|
||||
val options = listOf(
|
||||
initExistingProject to "--init",
|
||||
true to projectName,
|
||||
(location != null) to location,
|
||||
).makeOptions()
|
||||
return runtime.executeInteractive("new", *options) { eelProcess ->
|
||||
if (initExistingProject) {
|
||||
eelProcess.stdin.sendWholeText("$projectName\n")
|
||||
}
|
||||
Result.success("Created")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,12 +220,11 @@ class HatchCli(private val runtime: HatchRuntime) {
|
||||
}
|
||||
|
||||
|
||||
internal fun List<Pair<Boolean?, String?>>.makeOptions(): Array<String> {
|
||||
internal fun List<Pair<Boolean?, *>>.makeOptions(): Array<String> {
|
||||
return this.mapNotNull { (flag, option) ->
|
||||
when (flag) {
|
||||
true -> option
|
||||
false -> "$option=0"
|
||||
null -> null
|
||||
true -> option.toString()
|
||||
else -> null
|
||||
}
|
||||
}.toTypedArray()
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
package com.intellij.python.hatch.cli
|
||||
|
||||
import com.intellij.python.community.execService.ZeroCodeStdoutTransformer
|
||||
import com.intellij.python.hatch.HatchRuntime
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError.ExecException
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package com.intellij.python.hatch.cli
|
||||
|
||||
import com.intellij.python.community.execService.ZeroCodeStdoutTransformer
|
||||
import com.intellij.python.hatch.HatchRuntime
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError.ExecException
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.python.hatch.cli
|
||||
|
||||
import com.intellij.python.hatch.HatchRuntime
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.jetbrains.python.PythonHomePath
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError.ExecException
|
||||
import kotlinx.serialization.SerialName
|
||||
@@ -13,22 +15,22 @@ import java.nio.file.Path
|
||||
|
||||
@Suppress("unused")
|
||||
@Serializable
|
||||
class Environment(
|
||||
class HatchEnvironmentDetails(
|
||||
/**
|
||||
* An environment's type determines which environment plugin will be used for management.
|
||||
* The only built-in environment type is virtual, which uses virtual Python environments.
|
||||
*/
|
||||
val type: String,
|
||||
val type: @NlsSafe String,
|
||||
|
||||
/**
|
||||
* The python option specifies which version of Python to use, or an absolute path to a Python interpreter:
|
||||
*/
|
||||
val python: String? = null,
|
||||
val python: @NlsSafe String? = null,
|
||||
|
||||
/**
|
||||
* The description option is purely informational and is displayed in the output of the env show command:
|
||||
*/
|
||||
val description: String? = null,
|
||||
val description: @NlsSafe String? = null,
|
||||
|
||||
/**
|
||||
* A common use case is standalone environments that do not require inheritance nor the installation of the project,
|
||||
@@ -40,7 +42,7 @@ class Environment(
|
||||
/**
|
||||
* All environments inherit from the environment defined by its template option, which defaults to default.
|
||||
*/
|
||||
val template: String? = null,
|
||||
val template: @NlsSafe String? = null,
|
||||
|
||||
val installer: String? = null,
|
||||
|
||||
@@ -101,9 +103,10 @@ class Environment(
|
||||
val envExclude: List<String>? = null,
|
||||
)
|
||||
|
||||
typealias Environments = Map<String, Environment>
|
||||
typealias HatchDetailedEnvironments = Map<String, HatchEnvironmentDetails>
|
||||
|
||||
private const val DEFAULT_ENV_NAME: String = "default"
|
||||
const val DEFAULT_ENV_NAME: String = "default"
|
||||
const val ENV_TYPE_VIRTUAL: String = "virtual"
|
||||
|
||||
/**
|
||||
* Manage project environments
|
||||
@@ -138,7 +141,7 @@ class HatchEnv(runtime: HatchRuntime) : HatchCommand("env", runtime) {
|
||||
*
|
||||
* @return path to environment
|
||||
*/
|
||||
suspend fun find(envName: String? = null): Result<Path?, ExecException> {
|
||||
suspend fun find(envName: String? = null): Result<PythonHomePath?, ExecException> {
|
||||
val arguments = if (envName == null) emptyArray() else arrayOf(envName)
|
||||
return executeAndHandleErrors("find", *arguments) {
|
||||
when (it.exitCode) {
|
||||
@@ -191,29 +194,125 @@ class HatchEnv(runtime: HatchRuntime) : HatchCommand("env", runtime) {
|
||||
* Returns details of the specified environments.
|
||||
*
|
||||
* @param envs A vararg parameter specifying the environment names to be displayed. If not provided, information for all environments is shown.
|
||||
* @param internal Optional parameter indicating whether to include internal environments. Defaults to null.
|
||||
* @return A [Result] containing:
|
||||
* - [Environments] if operation is successful.
|
||||
* - [HatchDetailedEnvironments] if operation is successful.
|
||||
* - An error wrapped in [ExecException] if an execution failure occurs.
|
||||
*/
|
||||
suspend fun show(vararg envs: String, internal: Boolean? = null): Result<Environments, ExecException> {
|
||||
val options = listOf(internal to "--internal").makeOptions()
|
||||
return executeAndHandleErrors("show", "--json", *options, *envs) { processOutput ->
|
||||
suspend fun showWithDetails(vararg envs: String): Result<HatchDetailedEnvironments, ExecException> {
|
||||
return executeAndHandleErrors("show", "--json", *envs) { processOutput ->
|
||||
val output = processOutput.takeIf { it.exitCode == 0 }?.stdout
|
||||
?: return@executeAndHandleErrors Result.failure(null)
|
||||
|
||||
val json = Json { ignoreUnknownKeys = true }
|
||||
val jsonOutput = json.parseToJsonElement(output)
|
||||
val environments = if (internal == true) jsonOutput.jsonObject
|
||||
else {
|
||||
// JSON mode always shows internal environments, and there is no flag to distinguish them
|
||||
jsonOutput.jsonObject.filterKeys { !it.startsWith("hatch-") }
|
||||
}
|
||||
|
||||
// JSON mode always shows internal environments, and there is no flag to distinguish them
|
||||
val environments = jsonOutput.jsonObject.filterKeys { !it.startsWith("hatch-") }
|
||||
|
||||
val parsedEnvironments = environments.mapValues {
|
||||
json.decodeFromJsonElement<Environment>(it.value)
|
||||
json.decodeFromJsonElement<HatchEnvironmentDetails>(it.value)
|
||||
}
|
||||
Result.success(parsedEnvironments)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns details of the specified environments.
|
||||
*
|
||||
* @param envs A vararg parameter specifying the environment names to be displayed. If not provided, information for all environments is shown.
|
||||
* @param internal Optional parameter indicating whether to include internal environments. Defaults to false.
|
||||
* @return A [Result] containing:
|
||||
* - [HatchDetailedEnvironments] if operation is successful.
|
||||
* - An error wrapped in [ExecException] if an execution failure occurs.
|
||||
*/
|
||||
suspend fun show(vararg envs: String, internal: Boolean = false): Result<HatchEnvironments, ExecException> {
|
||||
val options = listOf(internal to "--internal").makeOptions()
|
||||
|
||||
val expectedOutput = """^\s+Standalone\s*\n((?:[+|].*[+|]\n)+)(?:\s+Matrices\s*\n((?:[+|].*[+|]\n)+))?$""".toRegex()
|
||||
|
||||
return executeAndMatch("show", "--ascii", *options, *envs, expectedOutput = expectedOutput) { matchResult ->
|
||||
val tables = buildMap {
|
||||
val (standaloneTable, matricesTable) = matchResult.destructured
|
||||
put(HatchEnvironmentType.STANDALONE, standaloneTable.parseHatchEnvironments())
|
||||
put(HatchEnvironmentType.MATRICES, matricesTable.parseHatchEnvironments())
|
||||
}
|
||||
Result.success(tables)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typealias HatchEnvironments = Map<HatchEnvironmentType, List<HatchEnvironment>>
|
||||
|
||||
enum class HatchEnvironmentType {
|
||||
STANDALONE,
|
||||
MATRICES,
|
||||
}
|
||||
|
||||
data class HatchEnvironment(
|
||||
val name: @NlsSafe String,
|
||||
val type: @NlsSafe String,
|
||||
val envs: String? = null,
|
||||
val features: String? = null,
|
||||
val dependencies: String? = null,
|
||||
val environmentVariables: String? = null,
|
||||
val scripts: String? = null,
|
||||
val description: String? = null,
|
||||
) {
|
||||
companion object {
|
||||
val DEFAULT: HatchEnvironment = HatchEnvironment(name = DEFAULT_ENV_NAME, type = ENV_TYPE_VIRTUAL)
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.parseHatchEnvironments(): List<HatchEnvironment> {
|
||||
val table = parseTable() ?: return emptyList()
|
||||
val nameIdx = table.findColumnIdx("Name") ?: error("Name column not found")
|
||||
val typeIdx = table.findColumnIdx("Type") ?: error("Type column not found")
|
||||
val envIdx = table.findColumnIdx("Env")
|
||||
val featuresIdx = table.findColumnIdx("Features")
|
||||
val dependenciesIdx = table.findColumnIdx("Features")
|
||||
val environmentVariablesIdx = table.findColumnIdx("EnvironmentVariables")
|
||||
val scriptsIdx = table.findColumnIdx("Scripts")
|
||||
val descriptionIdx = table.findColumnIdx("Description")
|
||||
|
||||
return table.rows.map { row ->
|
||||
HatchEnvironment(
|
||||
name = row[nameIdx],
|
||||
type = row[typeIdx],
|
||||
envs = envIdx?.let { row[it] },
|
||||
features = featuresIdx?.let { row[it] },
|
||||
dependencies = dependenciesIdx?.let { row[it] },
|
||||
environmentVariables = environmentVariablesIdx?.let { row[it] },
|
||||
scripts = scriptsIdx?.let { row[it] },
|
||||
description = descriptionIdx?.let { row[it] },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private data class Table(val headers: List<String>, val rows: List<List<String>>)
|
||||
|
||||
private fun Table.findColumnIdx(name: String): Int? = headers.indexOf(name).takeIf { it >= 0 }
|
||||
|
||||
|
||||
private fun String.parseTable(): Table? {
|
||||
val lines = this.trim().lines()
|
||||
val columns = lines.first().count { it == '+' } - 1
|
||||
if (columns <= 0) return null
|
||||
|
||||
val data = buildList {
|
||||
val currentRow = Array(columns) { "" }
|
||||
for (line in lines.drop(1)) {
|
||||
if (line.startsWith('+')) {
|
||||
add(currentRow.map { it.trim() })
|
||||
currentRow.fill("")
|
||||
continue
|
||||
}
|
||||
|
||||
val cells = line.splitToSequence('|').map { it.trim() }.toList()
|
||||
for (col in 0..<columns) {
|
||||
currentRow[col] += "\n${cells[col + 1]}"
|
||||
}
|
||||
}
|
||||
}
|
||||
return Table(headers = data.first(), rows = data.drop(1))
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.python.hatch.cli
|
||||
|
||||
import com.intellij.python.hatch.HatchRuntime
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError.ExecException
|
||||
import kotlinx.serialization.SerialName
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.intellij.python.hatch.cli
|
||||
|
||||
import com.intellij.execution.process.ProcessOutput
|
||||
import com.intellij.openapi.util.io.NioFiles
|
||||
import com.intellij.python.hatch.HatchRuntime
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.intellij.python.hatch.cli.HatchPython.PythonInstallResponse.AbortReason
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError.ExecException
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.python.hatch.cli
|
||||
|
||||
import com.intellij.python.hatch.HatchRuntime
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.intellij.python.hatch.PyHatchBundle
|
||||
import com.intellij.util.Url
|
||||
import com.intellij.util.Urls
|
||||
|
||||
@@ -1,52 +1,104 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.python.hatch
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import com.intellij.platform.eel.EelPlatform
|
||||
import com.intellij.platform.eel.provider.localEel
|
||||
import com.intellij.python.community.execService.ExecOptions
|
||||
import com.intellij.python.community.execService.WhatToExec
|
||||
import com.intellij.platform.eel.fs.EelFsError
|
||||
import com.intellij.python.hatch.cli.HatchEnvironment
|
||||
import com.intellij.python.hatch.service.CliBasedHatchService
|
||||
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
|
||||
import com.jetbrains.python.PythonBinary
|
||||
import com.jetbrains.python.PythonHomePath
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError
|
||||
import com.jetbrains.python.sdk.basePath
|
||||
import java.nio.file.Path
|
||||
|
||||
sealed class HatchError(message: @NlsSafe String) : PyError.Message(message)
|
||||
|
||||
class ExecutableNotFoundHatchError(path: Path?) : HatchError(
|
||||
class HatchExecutableNotFoundHatchError(path: Path?) : HatchError(
|
||||
PyHatchBundle.message("python.hatch.error.executable.is.not.found", path.toString())
|
||||
)
|
||||
|
||||
|
||||
fun EelApi.getHatchCommand(): String = when (platform) {
|
||||
is EelPlatform.Windows -> "hatch.exe"
|
||||
else -> "hatch"
|
||||
class BasePythonExecutableNotFoundHatchError(pathString: String?) : HatchError(
|
||||
PyHatchBundle.message("python.hatch.error.base.python.executable.is.not.found", pathString.toString())
|
||||
) {
|
||||
constructor(path: Path) : this(path.toString())
|
||||
}
|
||||
|
||||
suspend fun createHatchRuntime(
|
||||
workingDirectory: Path,
|
||||
envVars: Map<String, String> = emptyMap(),
|
||||
eelApi: EelApi = localEel,
|
||||
): Result<HatchRuntime, HatchError> {
|
||||
val hatchExecutable = HatchConfiguration.getOrDetectHatchExecutablePath(eelApi).getOr { return it }
|
||||
class WorkingDirectoryNotFoundHatchError(pathString: String?) : HatchError(
|
||||
PyHatchBundle.message("python.hatch.error.working.directory.is.not.found", pathString.toString())
|
||||
) {
|
||||
constructor(path: Path?) : this(path.toString())
|
||||
}
|
||||
|
||||
val defaultVariables = mapOf(
|
||||
HatchConstants.AppEnvVars.NO_COLOR to "1",
|
||||
HatchConstants.AppEnvVars.VERBOSE to "1",
|
||||
HatchConstants.AppEnvVars.INTERACTIVE to "0",
|
||||
"TERM" to "dumb",
|
||||
"COLUMNS" to "${0x7FFF}",
|
||||
"LINES" to "${0x7FFF}",
|
||||
)
|
||||
val actualEnvVars = defaultVariables + envVars
|
||||
class EnvironmentCreationHatchError(details: @NlsSafe String) : HatchError(
|
||||
PyHatchBundle.message("python.hatch.error.environment.creation", details)
|
||||
)
|
||||
|
||||
val runtime = HatchRuntime(
|
||||
hatchBinary = WhatToExec.Binary(hatchExecutable),
|
||||
execOptions = ExecOptions(
|
||||
env = actualEnvVars,
|
||||
workingDirectory = workingDirectory
|
||||
class FileSystemOperationHatchError(eelFsError: EelFsError) : HatchError(
|
||||
PyHatchBundle.message("python.hatch.error.filesystem.operation", eelFsError)
|
||||
)
|
||||
|
||||
|
||||
data class HatchStandaloneEnvironment(
|
||||
val hatchEnvironment: HatchEnvironment,
|
||||
val pythonVirtualEnvironment: PythonVirtualEnvironment,
|
||||
) {
|
||||
companion object {
|
||||
val AVAILABLE_ENVIRONMENTS_FOR_NEW_PROJECT: List<HatchStandaloneEnvironment> = listOf(
|
||||
HatchStandaloneEnvironment(HatchEnvironment.DEFAULT, PythonVirtualEnvironment.NotExisting())
|
||||
)
|
||||
)
|
||||
return Result.success(runtime)
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface PythonVirtualEnvironment {
|
||||
val pythonHomePath: PythonHomePath?
|
||||
|
||||
data class Existing(override val pythonHomePath: PythonHomePath, val pythonVersion: String) : PythonVirtualEnvironment
|
||||
data class NotExisting(override val pythonHomePath: PythonHomePath? = null) : PythonVirtualEnvironment
|
||||
}
|
||||
|
||||
interface HatchService {
|
||||
fun getWorkingDirectoryPath(): Path
|
||||
|
||||
@RequiresBackgroundThread
|
||||
suspend fun isHatchManagedProject(): Result<Boolean, PyError>
|
||||
|
||||
@RequiresBackgroundThread
|
||||
suspend fun createNewProject(projectName: String): Result<Unit, PyError>
|
||||
|
||||
/**
|
||||
* param[basePythonBinaryPath] base python for environment, the one on the PATH should be used if null.
|
||||
* param[envName] environment name to create, 'default' should be used if null.
|
||||
*/
|
||||
@RequiresBackgroundThread
|
||||
suspend fun createVirtualEnvironment(basePythonBinaryPath: PythonBinary? = null, envName: String? = null): Result<PythonVirtualEnvironment.Existing, PyError>
|
||||
|
||||
@RequiresBackgroundThread
|
||||
suspend fun findStandaloneEnvironments(): Result<List<HatchStandaloneEnvironment>, PyError>
|
||||
}
|
||||
|
||||
/**
|
||||
* Hatch Service for working directory (where hatch.toml / pyproject.toml is usually placed)
|
||||
*/
|
||||
@RequiresBackgroundThread
|
||||
suspend fun getHatchService(workingDirectoryPath: Path, hatchExecutablePath: Path? = null): Result<HatchService, PyError> {
|
||||
return CliBasedHatchService(hatchExecutablePath = hatchExecutablePath, workingDirectoryPath = workingDirectoryPath)
|
||||
}
|
||||
|
||||
/**
|
||||
* Hatch Service for Module.
|
||||
* Working directory considered as the module base path.
|
||||
*/
|
||||
@RequiresBackgroundThread
|
||||
suspend fun Module.getHatchService(hatchExecutablePath: Path? = null): Result<HatchService, PyError> {
|
||||
val workingDirectoryPath = basePath?.let { Path.of(it) }
|
||||
?: return Result.failure(WorkingDirectoryNotFoundHatchError(basePath))
|
||||
return getHatchService(workingDirectoryPath = workingDirectoryPath, hatchExecutablePath = hatchExecutablePath)
|
||||
}
|
||||
|
||||
/**
|
||||
* ../hatch/env/virtual/{normalized-project-name}/{hash}/{python-home}
|
||||
*/
|
||||
fun PythonHomePath.getHatchEnvVirtualProjectPath(): Path = this.parent.parent
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
package com.intellij.python.hatch
|
||||
package com.intellij.python.hatch.runtime
|
||||
|
||||
@Suppress("unused")
|
||||
object HatchConstants {
|
||||
@@ -41,4 +41,4 @@ object HatchConstants {
|
||||
object VersionEnvVars {
|
||||
const val VALIDATE_BUMP: String = "HATCH_VERSION_VALIDATE_BUMP"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package com.intellij.python.hatch.runtime
|
||||
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import com.intellij.platform.eel.provider.localEel
|
||||
import com.intellij.python.community.execService.*
|
||||
import com.intellij.python.hatch.BasePythonExecutableNotFoundHatchError
|
||||
import com.intellij.python.hatch.HatchConfiguration
|
||||
import com.intellij.python.hatch.HatchError
|
||||
import com.intellij.python.hatch.WorkingDirectoryNotFoundHatchError
|
||||
import com.intellij.python.hatch.cli.HatchCli
|
||||
import com.jetbrains.python.PythonBinary
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.isDirectory
|
||||
import kotlin.io.path.isExecutable
|
||||
|
||||
class HatchRuntime(
|
||||
val hatchBinary: WhatToExec.Binary,
|
||||
val execOptions: ExecOptions,
|
||||
private val execService: ExecService = ExecService(),
|
||||
) {
|
||||
fun hatchCli(): HatchCli = HatchCli(this)
|
||||
|
||||
fun withWorkingDirectory(workDirectoryPath: Path): Result<HatchRuntime, HatchError> {
|
||||
if (!workDirectoryPath.isDirectory()) {
|
||||
return Result.failure(WorkingDirectoryNotFoundHatchError(workDirectoryPath))
|
||||
}
|
||||
|
||||
val execOptions = with(this.execOptions) {
|
||||
ExecOptions(env, workDirectoryPath, processDescription, timeout)
|
||||
}
|
||||
return Result.success(HatchRuntime(this.hatchBinary, execOptions))
|
||||
}
|
||||
|
||||
fun withBasePythonBinaryPath(basePythonPath: PythonBinary): Result<HatchRuntime, HatchError> {
|
||||
if (!basePythonPath.isExecutable()) {
|
||||
return Result.failure(BasePythonExecutableNotFoundHatchError(basePythonPath))
|
||||
}
|
||||
|
||||
val execOptions = with(this.execOptions) {
|
||||
val modifiedEnv = env + mapOf(
|
||||
HatchConstants.AppEnvVars.PYTHON to basePythonPath.toString()
|
||||
)
|
||||
ExecOptions(modifiedEnv, workingDirectory, processDescription, timeout)
|
||||
}
|
||||
return Result.success(HatchRuntime(this.hatchBinary, execOptions))
|
||||
}
|
||||
|
||||
/**
|
||||
* Pure execution of [hatchBinary] with command line [arguments] and [execOptions] by [execService]
|
||||
* Doesn't make any validation of stdout/stderr content.
|
||||
*/
|
||||
internal suspend fun <T> execute(vararg arguments: String, processOutputTransformer: ProcessOutputTransformer<T>): Result<T, PyError.ExecException> {
|
||||
return execService.execute(hatchBinary, arguments.toList(), execOptions, processOutputTransformer)
|
||||
}
|
||||
|
||||
internal suspend fun <T> executeInteractive(vararg arguments: String, eelProcessInteractiveHandler: EelProcessInteractiveHandler<T>): Result<T, PyError.ExecException> {
|
||||
return execService.executeInteractive(hatchBinary, arguments.toList(), execOptions, eelProcessInteractiveHandler)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
suspend fun createHatchRuntime(
|
||||
hatchExecutablePath: Path?,
|
||||
workingDirectoryPath: Path?,
|
||||
envVars: Map<String, String> = emptyMap(),
|
||||
eelApi: EelApi = localEel,
|
||||
): Result<HatchRuntime, HatchError> {
|
||||
val actualHatchExecutable = hatchExecutablePath
|
||||
?: HatchConfiguration.getOrDetectHatchExecutablePath(eelApi).getOr { return it }
|
||||
if (workingDirectoryPath?.isDirectory() != true) {
|
||||
return Result.failure(WorkingDirectoryNotFoundHatchError(workingDirectoryPath))
|
||||
}
|
||||
|
||||
val defaultVariables = mapOf(
|
||||
HatchConstants.AppEnvVars.NO_COLOR to "1",
|
||||
HatchConstants.AppEnvVars.VERBOSE to "1",
|
||||
HatchConstants.AppEnvVars.INTERACTIVE to "0",
|
||||
"TERM" to "dumb",
|
||||
"COLUMNS" to "${0x7FFF}",
|
||||
"LINES" to "${0x7FFF}",
|
||||
)
|
||||
val actualEnvVars = defaultVariables + envVars
|
||||
|
||||
val runtime = HatchRuntime(
|
||||
hatchBinary = WhatToExec.Binary(actualHatchExecutable),
|
||||
execOptions = ExecOptions(
|
||||
env = actualEnvVars,
|
||||
workingDirectory = workingDirectoryPath
|
||||
)
|
||||
)
|
||||
return Result.success(runtime)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.intellij.python.hatch.runtime
|
||||
|
||||
import com.intellij.platform.eel.EelApi
|
||||
import com.intellij.platform.eel.EelPlatform
|
||||
|
||||
fun EelApi.getHatchCommand(): String = when (platform) {
|
||||
is EelPlatform.Windows -> "hatch.exe"
|
||||
else -> "hatch"
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.intellij.python.hatch.service
|
||||
|
||||
import com.intellij.platform.eel.fs.EelFileSystemApi
|
||||
import com.intellij.platform.eel.getOr
|
||||
import com.intellij.platform.eel.provider.asEelPath
|
||||
import com.intellij.platform.eel.provider.asNioPath
|
||||
import com.intellij.platform.eel.provider.getEelDescriptor
|
||||
import com.intellij.python.community.execService.ExecService
|
||||
import com.intellij.python.community.execService.WhatToExec.Binary
|
||||
import com.intellij.python.hatch.*
|
||||
import com.intellij.python.hatch.cli.HatchEnvironmentType
|
||||
import com.intellij.python.hatch.runtime.HatchRuntime
|
||||
import com.intellij.python.hatch.runtime.createHatchRuntime
|
||||
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
|
||||
import com.jetbrains.python.PythonBinary
|
||||
import com.jetbrains.python.PythonHomePath
|
||||
import com.jetbrains.python.Result
|
||||
import com.jetbrains.python.errorProcessing.PyError
|
||||
import com.jetbrains.python.resolvePythonBinary
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.exists
|
||||
import kotlin.io.path.isDirectory
|
||||
import kotlin.io.path.isRegularFile
|
||||
import kotlin.io.path.readText
|
||||
|
||||
internal class CliBasedHatchService private constructor(
|
||||
private val workingDirectoryPath: Path,
|
||||
private val hatchRuntime: HatchRuntime,
|
||||
) : HatchService {
|
||||
companion object {
|
||||
suspend operator fun invoke(workingDirectoryPath: Path, hatchExecutablePath: Path?): Result<CliBasedHatchService, PyError> {
|
||||
val hatchRuntime = createHatchRuntime(
|
||||
hatchExecutablePath=hatchExecutablePath,
|
||||
workingDirectoryPath=workingDirectoryPath,
|
||||
).getOr { return it }
|
||||
return Result.success(CliBasedHatchService(workingDirectoryPath, hatchRuntime))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getWorkingDirectoryPath(): Path = workingDirectoryPath
|
||||
|
||||
@RequiresBackgroundThread
|
||||
override suspend fun isHatchManagedProject(): Result<Boolean, PyError> {
|
||||
val isHatchManaged = when {
|
||||
workingDirectoryPath.resolve("hatch.toml").exists() -> true
|
||||
else -> {
|
||||
val pyProjectTomlPath = workingDirectoryPath.resolve("pyproject.toml").takeIf { it.isRegularFile() }
|
||||
val hatchRegex = """^\[tool\.hatch\..+]$""".toRegex(RegexOption.MULTILINE)
|
||||
pyProjectTomlPath?.readText()?.contains(hatchRegex) == true
|
||||
}
|
||||
}
|
||||
return Result.success(isHatchManaged)
|
||||
}
|
||||
|
||||
@RequiresBackgroundThread
|
||||
override suspend fun findStandaloneEnvironments(): Result<List<HatchStandaloneEnvironment>, PyError> {
|
||||
val hatchEnv = hatchRuntime.hatchCli().env()
|
||||
val environments = hatchEnv.show().getOr { return it }
|
||||
val standaloneEnvironments = environments.getOrDefault(HatchEnvironmentType.STANDALONE, emptyList())
|
||||
|
||||
val available = standaloneEnvironments.mapNotNull { env ->
|
||||
val pythonHomePath = hatchEnv.find(env.name).getOr { return@mapNotNull null } ?: return@mapNotNull null
|
||||
val pythonVirtualEnvironment = pythonHomePath.toPythonVirtualEnvironment().getOr { return@mapNotNull null }
|
||||
HatchStandaloneEnvironment(
|
||||
hatchEnvironment = env,
|
||||
pythonVirtualEnvironment = pythonVirtualEnvironment
|
||||
)
|
||||
}
|
||||
|
||||
return Result.success(available)
|
||||
}
|
||||
|
||||
@RequiresBackgroundThread
|
||||
override suspend fun createNewProject(projectName: String): Result<Unit, PyError> {
|
||||
val eelApi = workingDirectoryPath.getEelDescriptor().upgrade()
|
||||
val tempDir = eelApi.fs.createTemporaryDirectory(EelFileSystemApi.CreateTemporaryEntryOptions.Builder().build()).getOr { failure ->
|
||||
return Result.failure(FileSystemOperationHatchError(failure.error))
|
||||
}
|
||||
|
||||
hatchRuntime.hatchCli().new(projectName, tempDir.asNioPath()).getOr { return it }
|
||||
eelApi.fs.move(
|
||||
tempDir,
|
||||
workingDirectoryPath.asEelPath(),
|
||||
EelFileSystemApi.ReplaceExistingDuringMove.DO_NOT_REPLACE_DIRECTORIES,
|
||||
true
|
||||
).getOr { failure ->
|
||||
return Result.failure(FileSystemOperationHatchError(failure.error))
|
||||
}
|
||||
|
||||
return Result.success(Unit)
|
||||
}
|
||||
|
||||
@RequiresBackgroundThread
|
||||
override suspend fun createVirtualEnvironment(basePythonBinaryPath: PythonBinary?, envName: String?): Result<PythonVirtualEnvironment.Existing, PyError> {
|
||||
val pythonBasedRuntime = basePythonBinaryPath?.let { path ->
|
||||
hatchRuntime.withBasePythonBinaryPath(path).getOr { return it }
|
||||
} ?: hatchRuntime
|
||||
|
||||
val hatchEnv = pythonBasedRuntime.hatchCli().env()
|
||||
|
||||
hatchEnv.create(envName).getOr { return it }
|
||||
val pythonHomePath = hatchEnv.find(envName).getOr { return it }
|
||||
val pythonVirtualEnvironment = pythonHomePath?.toPythonVirtualEnvironment()?.getOr { return it }
|
||||
|
||||
val result = when (pythonVirtualEnvironment) {
|
||||
is PythonVirtualEnvironment.Existing -> Result.success(pythonVirtualEnvironment)
|
||||
else -> Result.failure(EnvironmentCreationHatchError("Hatch didn't create environment but responded with ok"))
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresBackgroundThread
|
||||
internal suspend fun PythonHomePath.toPythonVirtualEnvironment(): Result<PythonVirtualEnvironment, PyError> {
|
||||
val pythonVersion = this.takeIf { it.isDirectory() }?.resolvePythonBinary()?.let { pythonBinaryPath ->
|
||||
ExecService().execGetStdout(Binary(pythonBinaryPath), listOf("--version")).getOr { return it }.trim()
|
||||
}
|
||||
val pythonVirtualEnvironment = when {
|
||||
pythonVersion == null -> PythonVirtualEnvironment.NotExisting(this)
|
||||
else -> PythonVirtualEnvironment.Existing(this, pythonVersion)
|
||||
}
|
||||
return Result.success(pythonVirtualEnvironment)
|
||||
}
|
||||
Reference in New Issue
Block a user