passagemath-environment 10.5.43__py3-none-any.whl → 10.6.1rc2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {passagemath_environment-10.5.43.data → passagemath_environment-10.6.1rc2.data}/scripts/sage +1 -1
  2. {passagemath_environment-10.5.43.data → passagemath_environment-10.6.1rc2.data}/scripts/sage-env +3 -0
  3. passagemath_environment-10.6.1rc2.data/scripts/sage-version.sh +9 -0
  4. {passagemath_environment-10.5.43.dist-info → passagemath_environment-10.6.1rc2.dist-info}/METADATA +8 -8
  5. {passagemath_environment-10.5.43.dist-info → passagemath_environment-10.6.1rc2.dist-info}/RECORD +23 -22
  6. sage/env.py +65 -29
  7. sage/features/__init__.py +1 -1
  8. sage/features/all.py +1 -1
  9. sage/features/databases.py +76 -70
  10. sage/features/fricas.py +33 -4
  11. sage/features/giac.py +2 -2
  12. sage/features/latex.py +1 -1
  13. sage/features/latte.py +1 -1
  14. sage/features/meson_editable.py +45 -0
  15. sage/features/pkg_systems.py +1 -1
  16. sage/features/sagemath.py +1 -1
  17. sage/misc/package_dir.py +46 -7
  18. sage/version.py +4 -4
  19. passagemath_environment-10.5.43.data/scripts/sage-version.sh +0 -9
  20. {passagemath_environment-10.5.43.data → passagemath_environment-10.6.1rc2.data}/scripts/sage-num-threads.py +0 -0
  21. {passagemath_environment-10.5.43.data → passagemath_environment-10.6.1rc2.data}/scripts/sage-python +0 -0
  22. {passagemath_environment-10.5.43.data → passagemath_environment-10.6.1rc2.data}/scripts/sage-venv-config +0 -0
  23. {passagemath_environment-10.5.43.dist-info → passagemath_environment-10.6.1rc2.dist-info}/WHEEL +0 -0
  24. {passagemath_environment-10.5.43.dist-info → passagemath_environment-10.6.1rc2.dist-info}/top_level.txt +0 -0
@@ -433,7 +433,7 @@ usage_advanced() {
433
433
  echo " --failed -- only test files that failed last test"
434
434
  echo " --warn-long [timeout] -- warn if tests take too much CPU time"
435
435
  echo " --only-errors -- only output failures, not successes"
436
- echo " --gc=GC -- control garbarge collection (ALWAYS:"
436
+ echo " --gc=GC -- control garbage collection (ALWAYS:"
437
437
  echo " collect garbage before every test; NEVER:"
438
438
  echo " disable gc; DEFAULT: Python default)"
439
439
  echo " --short[=secs] -- run as many doctests as possible in about 300"
@@ -260,6 +260,9 @@ fi
260
260
  if [ -n "$SAGE_WHEELS_PATH" ]; then
261
261
  export PATH="$SAGE_WHEELS_PATH:$PATH"
262
262
  fi
263
+ if [ -d "$SAGE_ROOT"/tools ]; then
264
+ export PATH="$SAGE_ROOT/tools:$PATH"
265
+ fi
263
266
  if [ -d "$SAGE_ROOT" ]; then
264
267
  export PATH="$SAGE_ROOT/build/bin:$PATH"
265
268
  fi
@@ -0,0 +1,9 @@
1
+ # Sage version information for shell scripts.
2
+ #
3
+ # #31049: The following line is valid shell code but not valid Python code,
4
+ # which stops "setup.py develop" from rewriting it as a Python file.
5
+ :
6
+ # This file is auto-generated by the update-version script, do not edit!
7
+ SAGE_VERSION='10.6.1.rc2'
8
+ SAGE_RELEASE_DATE='2025-06-24'
9
+ SAGE_VERSION_BANNER='passagemath version 10.6.1.rc2, Release Date: 2025-06-24'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: passagemath-environment
3
- Version: 10.5.43
3
+ Version: 10.6.1rc2
4
4
  Summary: passagemath: System and software environment
5
5
  Author-email: The Sage Developers <sage-support@googlegroups.com>
6
6
  Maintainer: Matthias Köppe, passagemath contributors
@@ -19,21 +19,21 @@ Classifier: Intended Audience :: Science/Research
19
19
  Classifier: Operating System :: POSIX
20
20
  Classifier: Operating System :: MacOS :: MacOS X
21
21
  Classifier: Programming Language :: Python :: 3 :: Only
22
- Classifier: Programming Language :: Python :: 3.9
23
22
  Classifier: Programming Language :: Python :: 3.10
24
23
  Classifier: Programming Language :: Python :: 3.11
25
24
  Classifier: Programming Language :: Python :: 3.12
26
25
  Classifier: Programming Language :: Python :: 3.13
27
26
  Classifier: Programming Language :: Python :: Implementation :: CPython
28
27
  Classifier: Topic :: Scientific/Engineering :: Mathematics
29
- Requires-Python: <3.14,>=3.9
28
+ Requires-Python: <3.14,>=3.10
30
29
  Description-Content-Type: text/x-rst
30
+ Requires-Dist: platformdirs
31
31
  Provides-Extra: conf
32
- Requires-Dist: passagemath-conf~=10.5.43.0; extra == "conf"
32
+ Requires-Dist: passagemath-conf==10.6.1rc2; extra == "conf"
33
33
  Provides-Extra: docbuild
34
- Requires-Dist: passagemath-docbuild~=10.5.43.0; extra == "docbuild"
34
+ Requires-Dist: passagemath-docbuild==10.6.1rc2; extra == "docbuild"
35
35
  Provides-Extra: sage
36
- Requires-Dist: passagemath-standard~=10.5.43.0; extra == "sage"
36
+ Requires-Dist: passagemath-standard==10.6.1rc2; extra == "sage"
37
37
  Provides-Extra: cython
38
38
  Requires-Dist: cython!=3.0.3,<4.0,>=3.0; extra == "cython"
39
39
  Requires-Dist: cython<3.1.0,>=3.0.8; extra == "cython"
@@ -44,7 +44,7 @@ Requires-Dist: rst2ipynb>=0.2.2; extra == "rst2ipynb"
44
44
  Provides-Extra: tox
45
45
  Requires-Dist: tox>=4.11; extra == "tox"
46
46
  Provides-Extra: sws2rst
47
- Requires-Dist: passagemath-sws2rst~=10.5.43.0; extra == "sws2rst"
47
+ Requires-Dist: passagemath-sws2rst==10.6.1rc2; extra == "sws2rst"
48
48
 
49
49
  =========================================================================
50
50
  passagemath: System and software environment
@@ -87,7 +87,7 @@ passagemath attempts to support all major Linux distributions and recent version
87
87
  macOS. Use on Windows currently requires the use of Windows Subsystem for Linux or
88
88
  virtualization.
89
89
 
90
- Complete sets of binary wheels are provided on PyPI for Python versions 3.9.x-3.12.x.
90
+ Complete sets of binary wheels are provided on PyPI for Python versions 3.10.x-3.13.x.
91
91
  Python 3.13.x is also supported, but some third-party packages are still missing wheels,
92
92
  so compilation from source is triggered for those.
93
93
 
@@ -1,31 +1,31 @@
1
- passagemath_environment-10.5.43.data/scripts/sage,sha256=IjVLatRQBOGrVkqum1vDra9CZ0N7fkT0qfZNqJQRews,43367
2
- passagemath_environment-10.5.43.data/scripts/sage-env,sha256=bJMK-CihfTEImHt86_rR8vAlhTHpuzCNKvdv9MsDM6A,23497
3
- passagemath_environment-10.5.43.data/scripts/sage-num-threads.py,sha256=U09CpRe4aXkHNWHoZSYoQwYRASrvoT-l-zslRiGVbWc,3128
4
- passagemath_environment-10.5.43.data/scripts/sage-python,sha256=gXVskicH9NJtE5apMm1U-ZWDzWiz3Rm6dFBND2y60gI,28
5
- passagemath_environment-10.5.43.data/scripts/sage-venv-config,sha256=XeQOA2wIaIfUaEf9aPFUMQvr2s-aKKSLaBZORoSpP3Y,1371
6
- passagemath_environment-10.5.43.data/scripts/sage-version.sh,sha256=TGRh6PJD-eHVBqVKKIRtkRiS8AdoGZ7QizN5BVQ_nPY,403
1
+ passagemath_environment-10.6.1rc2.data/scripts/sage,sha256=ilfEQBFxVXUfnJSyU_fUkBKklipD5SFto5xCcvotJTI,43366
2
+ passagemath_environment-10.6.1rc2.data/scripts/sage-env,sha256=6mT6EF8r8gbIVkpZQCnYhh67VQulXGCABrG7pVgR73Y,23576
3
+ passagemath_environment-10.6.1rc2.data/scripts/sage-num-threads.py,sha256=U09CpRe4aXkHNWHoZSYoQwYRASrvoT-l-zslRiGVbWc,3128
4
+ passagemath_environment-10.6.1rc2.data/scripts/sage-python,sha256=gXVskicH9NJtE5apMm1U-ZWDzWiz3Rm6dFBND2y60gI,28
5
+ passagemath_environment-10.6.1rc2.data/scripts/sage-venv-config,sha256=XeQOA2wIaIfUaEf9aPFUMQvr2s-aKKSLaBZORoSpP3Y,1371
6
+ passagemath_environment-10.6.1rc2.data/scripts/sage-version.sh,sha256=V7FDqJYbCeAdKh5Pr1xj2HCPNRlCl-fIzwnjiV0pYuU,404
7
7
  sage/all__sagemath_environment.py,sha256=d44XIAz0tXfPdQxa3dGJvF2WEf6stMQxLUFL0GC1Sv4,188
8
- sage/env.py,sha256=7Oq3mOSIfX9fQ-1zb3J6zJn-1_mhALLA0jtfZfsLKw0,19497
9
- sage/version.py,sha256=__UAaaEbnKqMXtBlmRAiLjOtAWDpV1AvDP1PWDGAhxw,279
10
- sage/features/__init__.py,sha256=Q2AkXsk5rMmUoys8pfHUYBerGWZYxfk1ct_8m2skJn8,36976
11
- sage/features/all.py,sha256=6YQEvdLvw6Ipb0u-PLsB97wWnHj28qBYoz3fGbgrFmg,4236
8
+ sage/env.py,sha256=QAAwb71aDcFrPOzqZBVXpC1nqMcZEeu98FWhPWt7fZA,20528
9
+ sage/version.py,sha256=YfpxAF2k7-Dbv5uoRrk6DeNXh_GkwqUCmlpfpGOWPBE,280
10
+ sage/features/__init__.py,sha256=F20cLJt2e2gcaPFdQ9XyiLhjDuIZNQgtWx9PUA-3xSc,36970
11
+ sage/features/all.py,sha256=d7DJXcQMohA4J-tzim9ZkDPIt3SZ0c332fgcAyWOO9I,4238
12
12
  sage/features/bliss.py,sha256=SeLzXDEH30tgup593E42VJGGpR2gpRRI4lBt0ufCaGc,2447
13
13
  sage/features/cddlib.py,sha256=XieDFaChsJ9jJcQHaw0Zxy3Mi7YfoeTDRJWzi81eEVg,1484
14
14
  sage/features/coxeter3.py,sha256=FwmbW2JsER7j8KGonUEDe0Mfn-5QndDY2gGLcS84gso,1475
15
15
  sage/features/csdp.py,sha256=gen-XGjD-BcbOojILWv9L-T1zamb0_qFRlshk0k_j-k,2849
16
16
  sage/features/cython.py,sha256=iCIV3-Btwv6vX2L15cbCyHuNx71-xcLcpwt6wCYC1Xc,1291
17
- sage/features/databases.py,sha256=N1mk0bDzM27FkKyc4MHeZFhQAszusfX7ixt4bnb7xxs,10994
17
+ sage/features/databases.py,sha256=iA1RKM_ZueF-9pX66djglZm4uprQQ9ezlCJwgMlpZpU,10462
18
18
  sage/features/dot2tex.py,sha256=xW_d8nroNiI_LDuy3qLH30qDnOSyDJcGmIegDRODIgE,1266
19
19
  sage/features/dvipng.py,sha256=K-8iEGjmv0OFkdQfbNmncsfFXYhG6lz8FcY1XAcKgoM,1331
20
20
  sage/features/eclib.py,sha256=tP9rUZ2_vTe02cI49hV3WeTgwVvJ1VkJmzTN9VEOPtc,1499
21
21
  sage/features/ecm.py,sha256=LdvVZwAmzD0wx2qOJIvcHo2HHCwDg_xk2x7jWRumnWA,1627
22
22
  sage/features/ffmpeg.py,sha256=yG4zgEAlVAGAxFou_tynAufRFbYdxKwyNXz_ev9QR2k,4759
23
23
  sage/features/four_ti_2.py,sha256=fKuKtWscuOCF4T1v8iNAlkRxSfyfp_1M-W4l9xaG6gg,1723
24
- sage/features/fricas.py,sha256=vaNrVBL5TxLs6RfGRWLBeczPYOM7yQQnCAva_q7Yhik,2582
24
+ sage/features/fricas.py,sha256=eQ6er3cCw080ke0UMf2XvKtJtTzHBhwsk6Vvia5RkkI,3899
25
25
  sage/features/frobby.py,sha256=ITL0J4N4MKN2yuBKS6c-1vw_R7nZr72ZoPKeXi3JJVg,1500
26
26
  sage/features/gap.py,sha256=cmjZ8AGA1Lk9tgWw03VJeCMq1eMZgmhbAvOkRzLk7Xs,3375
27
27
  sage/features/gfan.py,sha256=RqWVutlkcLcMG5lSvHj_EobFhjhz2_mIzf1oJPbJ5eY,1474
28
- sage/features/giac.py,sha256=kNrJqje0kGh9d9Nw9C7UWuh3O6wDWuDf8qw1uTuZ5t8,1025
28
+ sage/features/giac.py,sha256=EOkaMtlY83eg36IqnScYZEYY5rqVx8HOplQf7SZP5L0,1025
29
29
  sage/features/graph_generators.py,sha256=YW9QgjD4Jf_clpg9Q3rZZnPmurzglumkz2NAg32JBkI,6219
30
30
  sage/features/graphviz.py,sha256=BY9LU2-p9a3uvw8L07CVDDMiznyzJajFi1W7fb0T2pQ,3516
31
31
  sage/features/igraph.py,sha256=PS5bMx-2AH99xFeSBNWBwfAKHL5DNud2QRGNtRWezrc,1493
@@ -36,12 +36,13 @@ sage/features/internet.py,sha256=he6OLOrLihRrkWCCKVwyBGZyXmU7XRP-ZWfUPR_A1C4,207
36
36
  sage/features/jmol.py,sha256=Gg7vTzNRJoPIQSbF25gifJvqHJDn0dm5HZTEA4TMdNA,1135
37
37
  sage/features/join_feature.py,sha256=5UqBs4DCUZddchINdg_HTIKLESOC0scm9u3lsIImmuY,5376
38
38
  sage/features/kenzo.py,sha256=wg74fq-SlaULV8nxQBu3YRHNaU0HRIWPt1CujECAOAM,2673
39
- sage/features/latex.py,sha256=RlAiKh9D3ueNR7oVnM5l3MHytHGvLeDZpwbwBZKBfeI,9617
40
- sage/features/latte.py,sha256=lmVKos8_f9UJjU1nSVuAWURM80fsYIv1n1do-5pCbd4,2787
39
+ sage/features/latex.py,sha256=h6Cdy3YR2gSUyDJnQ5pwuvmLPetZDyQWQ9SQ60iT-vk,9611
40
+ sage/features/latte.py,sha256=Oums14ZgCxI8a6Y4xH7Ts9yJUggln2XZhXcfKciAvRs,2786
41
41
  sage/features/lrs.py,sha256=ru_VDo0Y6am54FQd9zqanhqoXnZXP2hudnkjD9GNNlI,5963
42
42
  sage/features/macaulay2.py,sha256=FcCgcuYw5leJowUEaRzBSMF4ZdKN6irzav6JBW7YYdk,1566
43
43
  sage/features/mcqd.py,sha256=GfllBC9A170B0z64bE3AZ9yLfUF8aTdQDgGhRwCnYGc,1397
44
44
  sage/features/meataxe.py,sha256=9uYHmPzED2RGmK5ge56zJlnHDhKVQidPEbxLThSdiaw,1458
45
+ sage/features/meson_editable.py,sha256=yAP3uRo-B2F2lGpK4eMXqscpQFiQ9MnhU6QYGx01ZAk,1211
45
46
  sage/features/mip_backends.py,sha256=3NcBZMtpc8ga0ZJ_mKpdhuCFCRlfWwprrQYdH8ERBxU,4659
46
47
  sage/features/msolve.py,sha256=G3ohDA51kQ9OrliGCX--j_5MldsWw-hJtG_LrJKho4c,2508
47
48
  sage/features/nauty.py,sha256=RxY4q1skVUYFNYl00mNb93Z2W9wQHYPVxB46B7rDIcY,2341
@@ -51,12 +52,12 @@ sage/features/pandoc.py,sha256=znyRzmwjtdx16DPIkeU2hTxylRfntUfwgefcMYvVo8o,1358
51
52
  sage/features/pari.py,sha256=Fck_0LMUHP_73JFuQgexKenM-maXo0zyiZMTSilaNRU,1232
52
53
  sage/features/pdf2svg.py,sha256=jcIpG_iFG9VG6cN4eoDrvVXTAUCkRDvwdH46olphxxw,1413
53
54
  sage/features/phitigra.py,sha256=VBWeUOd4lJTUr-M9IDJE2SkoUsHmtyD3N3fNDVQDf8c,1292
54
- sage/features/pkg_systems.py,sha256=GOyVswRAAFqQ_oSZOZz-IA51c7a4N77tnQkfZ69xukY,6995
55
+ sage/features/pkg_systems.py,sha256=50kXBO_1gb6WH6SZMVob1Los1VVs_fjP0W7eO4Pe0rM,6989
55
56
  sage/features/polymake.py,sha256=Ix2qM0izHhBFa-IGTWjcbW9ofutbRP6FTL5p4buSgPU,1429
56
57
  sage/features/poppler.py,sha256=orH2EOrKcUKFVKcNBRE4f0-9djOQWqJwWnEL17u9mrg,2233
57
58
  sage/features/qepcad.py,sha256=hD7TY_e9tCAqGyVHzsij4sOkDejzxvf-KMsqLB5JeLE,1495
58
59
  sage/features/rubiks.py,sha256=NF6ebywycUBA4n-e5rf4_KRPv7qLrkLi7Y_qTkl_gTI,5353
59
- sage/features/sagemath.py,sha256=sXAkGnYOyNEb8xxdF7GCSLt4Z5-oCnZ-VnZdeyEes8M,56821
60
+ sage/features/sagemath.py,sha256=8nxEIvd-EwGrVoluTGPwBWEDrjJMudUwCiF9OdbiV8o,56821
60
61
  sage/features/sat.py,sha256=iHbfPD1yq5xqnBKmnetVIkKUPnjApTQfCw_s1D2qfcc,2921
61
62
  sage/features/singular.py,sha256=jyX5Pl-Zpo-I5kG0aKDFdPawMcM_S_Jv0QN7dsENNRg,1611
62
63
  sage/features/sirocco.py,sha256=wWG1tWXFnUPY5XVL5eQXKSQiX4g-bwsMXekIltbVQFs,1452
@@ -71,10 +72,10 @@ sage/features/threejs.py,sha256=6oanR1omSvCAEDmwh1xiiPjFM648K66_oLQT6nyz_Q0,2368
71
72
  sage/features/topcom.py,sha256=swLvRxLgXZ3zg6-y0Pbh9ci6vGqsVEoTXJXf-UI_8nA,2211
72
73
  sage/misc/all__sagemath_environment.py,sha256=LG7rw2H1bgnbQpXTph34n1ULnjE3vu4jViJEZE8M9lQ,109
73
74
  sage/misc/package.py,sha256=xZF5iijW69X9DblpnLcYXQiRdjE7Uhu1MJ5eeq12T9o,19191
74
- sage/misc/package_dir.py,sha256=oZ7gIoZFq2pTSeM0hW2RISg9p5MIs9npgLNQlKdBlk0,26898
75
+ sage/misc/package_dir.py,sha256=O0mWpmN95RRv2rs3usNb_GTL2T9fZiJNOl6WyQiophs,28576
75
76
  sage/misc/temporary_file.py,sha256=U16AQcCP5NZXO-HXt8IutcFfOdEerf2Zc6FfG9-odmU,19571
76
77
  sage/misc/viewer.py,sha256=Jm4pABqyMs1hvggLA0JZAiZ_26uaBtPpaRKQUTddVE4,11574
77
- passagemath_environment-10.5.43.dist-info/METADATA,sha256=dwhBWth0T_KJb0mP2KfmiDKWTC3Xd8heX5JD_Ak2N9Y,5524
78
- passagemath_environment-10.5.43.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
79
- passagemath_environment-10.5.43.dist-info/top_level.txt,sha256=hibFyzQHiLOMK68qL1OWsNKaXOmSXqZjeLTBem6Yy7I,5
80
- passagemath_environment-10.5.43.dist-info/RECORD,,
78
+ passagemath_environment-10.6.1rc2.dist-info/METADATA,sha256=Kxs-6Sqa1g9PAuJ8vFIcmG1m5snqVBQ-sJExlwSI6Fk,5506
79
+ passagemath_environment-10.6.1rc2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
80
+ passagemath_environment-10.6.1rc2.dist-info/top_level.txt,sha256=hibFyzQHiLOMK68qL1OWsNKaXOmSXqZjeLTBem6Yy7I,5
81
+ passagemath_environment-10.6.1rc2.dist-info/RECORD,,
sage/env.py CHANGED
@@ -39,23 +39,22 @@ AUTHORS:
39
39
  # https://www.gnu.org/licenses/
40
40
  # ****************************************************************************
41
41
 
42
- from typing import Optional
43
- import sage
44
- import platform
45
42
  import os
46
43
  import socket
44
+ import subprocess
47
45
  import sys
48
46
  import sysconfig
49
- from . import version
50
- from pathlib import Path
51
- import subprocess
47
+ from typing import Optional
52
48
 
49
+ from platformdirs import site_data_dir, user_data_dir
50
+
51
+ from sage import version
53
52
 
54
53
  # All variables set by var() appear in this SAGE_ENV dict
55
54
  SAGE_ENV = dict()
56
55
 
57
56
 
58
- def join(*args):
57
+ def join(*args) -> str | None:
59
58
  """
60
59
  Join paths like ``os.path.join`` except that the result is ``None``
61
60
  if any of the components is ``None``.
@@ -193,7 +192,7 @@ SAGE_LOCAL_SPKG_INST = var("SAGE_LOCAL_SPKG_INST", join(SAGE_LOCAL, "var", "lib"
193
192
  SAGE_SPKG_INST = var("SAGE_SPKG_INST", join(SAGE_LOCAL, "var", "lib", "sage", "installed")) # deprecated
194
193
 
195
194
  # source tree of the Sage distribution
196
- SAGE_ROOT = var("SAGE_ROOT") # no fallback for SAGE_ROOT
195
+ SAGE_ROOT = var("SAGE_ROOT") or None
197
196
  SAGE_SRC = var("SAGE_SRC", join(SAGE_ROOT, "src"), SAGE_LIB)
198
197
  SAGE_DOC_SRC = var("SAGE_DOC_SRC", join(SAGE_ROOT, "src", "doc"), SAGE_DOC)
199
198
  SAGE_PKGS = var("SAGE_PKGS", join(SAGE_ROOT, "build", "pkgs"))
@@ -205,30 +204,20 @@ SAGE_DOC_SERVER_URL = var("SAGE_DOC_SERVER_URL")
205
204
  SAGE_DOC_LOCAL_PORT = var("SAGE_DOC_LOCAL_PORT", "0")
206
205
 
207
206
  # ~/.sage
208
- DOT_SAGE = var("DOT_SAGE", join(os.environ.get("HOME"), ".sage"))
207
+ if sys.platform == 'win32':
208
+ home_dir = os.environ.get("USERPROFILE")
209
+ else: # Unix-like systems (Linux, macOS, etc.)
210
+ home_dir = os.environ.get("HOME")
211
+ DOT_SAGE = var("DOT_SAGE", join(home_dir, ".sage"))
209
212
  SAGE_STARTUP_FILE = var("SAGE_STARTUP_FILE", join(DOT_SAGE, "init.sage"))
210
213
 
211
214
  # for sage_setup.setenv
212
215
  SAGE_ARCHFLAGS = var("SAGE_ARCHFLAGS", "unset")
213
216
  SAGE_PKG_CONFIG_PATH = var("SAGE_PKG_CONFIG_PATH")
214
217
 
215
- try:
216
- import sage_wheels
217
- except ImportError:
218
- _sage_wheels_path = []
219
- else:
220
- _sage_wheels_path = sage_wheels.__path__
221
-
222
- # colon-separated search path for databases.
223
- SAGE_DATA_PATH = var("SAGE_DATA_PATH",
224
- os.pathsep.join(filter(None, [
225
- join(DOT_SAGE, "db"),
226
- ] + [
227
- join(p, "share") for p in _sage_wheels_path
228
- ] + [
229
- join(SAGE_SHARE, "sagemath"),
230
- SAGE_SHARE,
231
- ])))
218
+ # colon-separated search path for databases
219
+ # should not be used directly; instead use sage_data_paths
220
+ SAGE_DATA_PATH = var("SAGE_DATA_PATH")
232
221
 
233
222
  # database directories, the default is to search in SAGE_DATA_PATH
234
223
  CREMONA_LARGE_DATA_DIR = var("CREMONA_LARGE_DATA_DIR")
@@ -373,6 +362,10 @@ def sage_include_directories(use_sources=False):
373
362
  sage: dirs = sage.env.sage_include_directories(use_sources=True)
374
363
  sage: any(os.path.isfile(os.path.join(d, file)) for d in dirs)
375
364
  True
365
+
366
+ ::
367
+
368
+ sage: # optional - !meson_editable (no need, see :issue:`39275`)
376
369
  sage: dirs = sage.env.sage_include_directories(use_sources=False)
377
370
  sage: any(os.path.isfile(os.path.join(d, file)) for d in dirs)
378
371
  True
@@ -462,9 +455,10 @@ def cython_aliases(required_modules=None, optional_modules=None):
462
455
  ....: ''')
463
456
  435
464
457
  """
465
- import pkgconfig
466
458
  import itertools
467
459
 
460
+ import pkgconfig
461
+
468
462
  if required_modules is None:
469
463
  required_modules = default_required_modules
470
464
 
@@ -524,10 +518,11 @@ def cython_aliases(required_modules=None, optional_modules=None):
524
518
  aliases[var + "LIBRARIES"] = pc['libraries']
525
519
 
526
520
  # uname-specific flags
527
- UNAME = os.uname()
521
+ import platform
522
+ system = platform.system()
528
523
 
529
524
  def uname_specific(name, value, alternative):
530
- if name in UNAME[0]:
525
+ if system == name:
531
526
  return value
532
527
  else:
533
528
  return alternative
@@ -535,6 +530,8 @@ def cython_aliases(required_modules=None, optional_modules=None):
535
530
  aliases["LINUX_NOEXECSTACK"] = uname_specific("Linux", ["-Wl,-z,noexecstack"],
536
531
  [])
537
532
 
533
+ aliases["M_LIBRARIES"] = uname_specific("Windows", [], ["m"])
534
+
538
535
  # LinBox needs special care because it actually requires C++11 with
539
536
  # GNU extensions: -std=c++11 does not work, you need -std=gnu++11
540
537
  # (this is true at least with GCC 7.2.0).
@@ -563,3 +560,42 @@ def cython_aliases(required_modules=None, optional_modules=None):
563
560
  aliases["OPENMP_CXXFLAGS"] = OPENMP_CXXFLAGS.split()
564
561
 
565
562
  return aliases
563
+
564
+
565
+ def sage_data_paths(name: str | None) -> set[str]:
566
+ r"""
567
+ Search paths for general data files.
568
+
569
+ If specified, the subdirectory ``name`` is appended to the
570
+ directories. Otherwise, the directories are returned as is.
571
+
572
+ EXAMPLES::
573
+
574
+ sage: from sage.env import sage_data_paths
575
+ sage: sage_data_paths("cremona")
576
+ {'.../cremona'}
577
+ """
578
+ if not SAGE_DATA_PATH:
579
+ paths = {
580
+ join(DOT_SAGE, "db"),
581
+ join(SAGE_SHARE, "sagemath"),
582
+ SAGE_SHARE,
583
+ }
584
+ try:
585
+ import sage_wheels
586
+ except ImportError:
587
+ _sage_wheels_path = []
588
+ else:
589
+ _sage_wheels_path = sage_wheels.__path__
590
+ for p in _sage_wheels_path:
591
+ paths.add(join(p, "share"))
592
+ paths.add(user_data_dir("sagemath"))
593
+ paths.add(user_data_dir())
594
+ paths.add(site_data_dir("sagemath"))
595
+ paths.add(site_data_dir())
596
+ else:
597
+ paths = {path for path in SAGE_DATA_PATH.split(os.pathsep)}
598
+
599
+ if name is None:
600
+ return {path for path in paths if path}
601
+ return {os.path.join(path, name) for path in paths if path}
sage/features/__init__.py CHANGED
@@ -566,7 +566,7 @@ def package_systems():
566
566
  [Feature('homebrew'), Feature('sage_spkg'), Feature('pip')]
567
567
  """
568
568
  # The current implementation never returns more than one system.
569
- from subprocess import run, CalledProcessError, PIPE
569
+ from subprocess import run, CalledProcessError
570
570
  global _cache_package_systems
571
571
  if _cache_package_systems is None:
572
572
  from .pkg_systems import PackageSystem, SagePackageSystem, PipPackageSystem
sage/features/all.py CHANGED
@@ -117,7 +117,7 @@ def name_feature(name, toplevel=None):
117
117
  except AttributeError:
118
118
  return None
119
119
 
120
- from sage.misc.dev_tools import find_object_modules
120
+ from sage.misc.sageinspect import find_object_modules
121
121
 
122
122
  for module, names in find_object_modules(obj).items():
123
123
  if name in names and (feature := module_feature(module)):
@@ -17,27 +17,8 @@ Features for testing the presence of various databases
17
17
  # https://www.gnu.org/licenses/
18
18
  # *****************************************************************************
19
19
 
20
- import os
21
-
22
- from . import StaticFile, PythonModule
23
- from sage.env import SAGE_DATA_PATH
24
-
25
-
26
- def sage_data_path(data_name):
27
- r"""
28
- Search path for database ``data_name``.
29
-
30
- EXAMPLES::
31
-
32
- sage: from sage.features.databases import sage_data_path
33
- sage: sage_data_path("cremona")
34
- ['.../cremona']
35
- """
36
- if not SAGE_DATA_PATH:
37
- return []
38
-
39
- return [os.path.join(p, data_name)
40
- for p in SAGE_DATA_PATH.split(os.pathsep)]
20
+ from sage.env import sage_data_paths
21
+ from sage.features import PythonModule, StaticFile
41
22
 
42
23
 
43
24
  class DatabaseCremona(StaticFile):
@@ -58,7 +39,10 @@ class DatabaseCremona(StaticFile):
58
39
  sage: DatabaseCremona().is_present() # optional - database_cremona_ellcurve
59
40
  FeatureTestResult('database_cremona_ellcurve', True)
60
41
  """
61
- def __init__(self, name='cremona', spkg='database_cremona_ellcurve', type='optional'):
42
+
43
+ def __init__(
44
+ self, name="cremona", spkg="database_cremona_ellcurve", type="optional"
45
+ ):
62
46
  r"""
63
47
  TESTS::
64
48
 
@@ -66,24 +50,28 @@ class DatabaseCremona(StaticFile):
66
50
  sage: isinstance(DatabaseCremona(), DatabaseCremona)
67
51
  True
68
52
  """
69
- from sage.env import CREMONA_MINI_DATA_DIR, CREMONA_LARGE_DATA_DIR
53
+ from sage.env import CREMONA_LARGE_DATA_DIR, CREMONA_MINI_DATA_DIR
54
+
70
55
  CREMONA_DATA_DIRS = set([CREMONA_MINI_DATA_DIR, CREMONA_LARGE_DATA_DIR])
71
56
  CREMONA_DATA_DIRS.discard(None)
72
- search_path = list(CREMONA_DATA_DIRS) + sage_data_path("cremona")
57
+ search_path = list(CREMONA_DATA_DIRS) + list(sage_data_paths("cremona"))
73
58
 
74
59
  spkg = "database_cremona_ellcurve"
75
60
  spkg_type = "optional"
76
- if name == 'cremona_mini':
61
+ if name == "cremona_mini":
77
62
  spkg = "elliptic_curves"
78
63
  spkg_type = "standard"
79
64
 
80
- StaticFile.__init__(self, f"database_{name}_ellcurve",
81
- filename=f"{name}.db",
82
- search_path=search_path,
83
- spkg=spkg,
84
- type=spkg_type,
85
- url='https://github.com/JohnCremona/ecdata',
86
- description="Cremona's database of elliptic curves")
65
+ StaticFile.__init__(
66
+ self,
67
+ f"database_{name}_ellcurve",
68
+ filename=f"{name}.db",
69
+ search_path=search_path,
70
+ spkg=spkg,
71
+ type=spkg_type,
72
+ url="https://github.com/JohnCremona/ecdata",
73
+ description="Cremona's database of elliptic curves",
74
+ )
87
75
 
88
76
 
89
77
  class DatabaseEllcurves(StaticFile):
@@ -97,6 +85,7 @@ class DatabaseEllcurves(StaticFile):
97
85
  sage: bool(DatabaseEllcurves().is_present()) # optional - database_ellcurves
98
86
  True
99
87
  """
88
+
100
89
  def __init__(self):
101
90
  r"""
102
91
  TESTS::
@@ -109,14 +98,19 @@ class DatabaseEllcurves(StaticFile):
109
98
  search_path = []
110
99
  if ELLCURVE_DATA_DIR is not None:
111
100
  search_path.append(ELLCURVE_DATA_DIR)
112
- search_path.extend(sage_data_path("ellcurves"))
101
+ search_path.extend(sage_data_paths("ellcurves"))
102
+
103
+ search_path = ELLCURVE_DATA_DIR or sage_data_paths("ellcurves")
113
104
 
114
- StaticFile.__init__(self, "database_ellcurves",
115
- filename='rank0',
116
- search_path=search_path,
117
- spkg='elliptic_curves',
118
- type='standard',
119
- description="William Stein's database of interesting curve")
105
+ StaticFile.__init__(
106
+ self,
107
+ "database_ellcurves",
108
+ filename="rank0",
109
+ search_path=search_path,
110
+ spkg="elliptic_curves",
111
+ type="standard",
112
+ description="William Stein's database of interesting curve",
113
+ )
120
114
 
121
115
 
122
116
  class DatabaseGraphs(StaticFile):
@@ -130,6 +124,7 @@ class DatabaseGraphs(StaticFile):
130
124
  sage: bool(DatabaseGraphs().is_present()) # optional - database_graphs
131
125
  True
132
126
  """
127
+
133
128
  def __init__(self):
134
129
  r"""
135
130
  TESTS::
@@ -142,14 +137,17 @@ class DatabaseGraphs(StaticFile):
142
137
  search_path = []
143
138
  if GRAPHS_DATA_DIR is not None:
144
139
  search_path.append(GRAPHS_DATA_DIR)
145
- search_path.extend(sage_data_path("graphs"))
140
+ search_path.extend(sage_data_paths("graphs"))
146
141
 
147
- StaticFile.__init__(self, "database_graphs",
148
- filename='graphs.db',
149
- search_path=search_path,
150
- spkg='graphs',
151
- type='standard',
152
- description="A database of graphs")
142
+ StaticFile.__init__(
143
+ self,
144
+ "database_graphs",
145
+ filename="graphs.db",
146
+ search_path=search_path,
147
+ spkg="graphs",
148
+ type="standard",
149
+ description="A database of graphs",
150
+ )
153
151
 
154
152
 
155
153
  class DatabaseJones(StaticFile):
@@ -163,6 +161,7 @@ class DatabaseJones(StaticFile):
163
161
  sage: bool(DatabaseJones().is_present()) # optional - database_jones_numfield
164
162
  True
165
163
  """
164
+
166
165
  def __init__(self):
167
166
  r"""
168
167
  TESTS::
@@ -171,11 +170,14 @@ class DatabaseJones(StaticFile):
171
170
  sage: isinstance(DatabaseJones(), DatabaseJones)
172
171
  True
173
172
  """
174
- StaticFile.__init__(self, "database_jones_numfield",
175
- filename='jones.sobj',
176
- search_path=sage_data_path("jones"),
177
- spkg='database_jones_numfield',
178
- description="John Jones's tables of number fields")
173
+ StaticFile.__init__(
174
+ self,
175
+ "database_jones_numfield",
176
+ filename="jones.sobj",
177
+ search_path=sage_data_paths("jones"),
178
+ spkg="database_jones_numfield",
179
+ description="John Jones's tables of number fields",
180
+ )
179
181
 
180
182
 
181
183
  class DatabaseKnotInfo(PythonModule):
@@ -193,6 +195,7 @@ class DatabaseKnotInfo(PythonModule):
193
195
  sage: DatabaseKnotInfo().is_present() # optional - database_knotinfo
194
196
  FeatureTestResult('database_knotinfo', True)
195
197
  """
198
+
196
199
  def __init__(self):
197
200
  r"""
198
201
  TESTS::
@@ -201,7 +204,7 @@ class DatabaseKnotInfo(PythonModule):
201
204
  sage: isinstance(DatabaseKnotInfo(), DatabaseKnotInfo)
202
205
  True
203
206
  """
204
- PythonModule.__init__(self, 'database_knotinfo', spkg='database_knotinfo')
207
+ PythonModule.__init__(self, "database_knotinfo", spkg="database_knotinfo")
205
208
 
206
209
 
207
210
  class DatabaseMatroids(PythonModule):
@@ -219,6 +222,7 @@ class DatabaseMatroids(PythonModule):
219
222
 
220
223
  [Mat2012]_
221
224
  """
225
+
222
226
  def __init__(self):
223
227
  r"""
224
228
  TESTS::
@@ -227,7 +231,7 @@ class DatabaseMatroids(PythonModule):
227
231
  sage: isinstance(DatabaseMatroids(), DatabaseMatroids)
228
232
  True
229
233
  """
230
- PythonModule.__init__(self, 'matroid_database', spkg='matroid_database')
234
+ PythonModule.__init__(self, "matroid_database", spkg="matroid_database")
231
235
 
232
236
 
233
237
  class DatabaseCubicHecke(PythonModule):
@@ -245,6 +249,7 @@ class DatabaseCubicHecke(PythonModule):
245
249
  sage: DatabaseCubicHecke().is_present() # optional - database_cubic_hecke
246
250
  FeatureTestResult('database_cubic_hecke', True)
247
251
  """
252
+
248
253
  def __init__(self):
249
254
  r"""
250
255
  TESTS::
@@ -253,7 +258,7 @@ class DatabaseCubicHecke(PythonModule):
253
258
  sage: isinstance(DatabaseCubicHecke(), DatabaseCubicHecke)
254
259
  True
255
260
  """
256
- PythonModule.__init__(self, 'database_cubic_hecke', spkg='database_cubic_hecke')
261
+ PythonModule.__init__(self, "database_cubic_hecke", spkg="database_cubic_hecke")
257
262
 
258
263
 
259
264
  class DatabaseReflexivePolytopes(StaticFile):
@@ -270,7 +275,8 @@ class DatabaseReflexivePolytopes(StaticFile):
270
275
  sage: bool(DatabaseReflexivePolytopes('polytopes_db_4d').is_present()) # optional - polytopes_db_4d
271
276
  True
272
277
  """
273
- def __init__(self, name='polytopes_db'):
278
+
279
+ def __init__(self, name="polytopes_db"):
274
280
  """
275
281
  TESTS::
276
282
 
@@ -286,26 +292,26 @@ class DatabaseReflexivePolytopes(StaticFile):
286
292
  search_path = []
287
293
  if POLYTOPE_DATA_DIR is not None:
288
294
  search_path.append(POLYTOPE_DATA_DIR)
289
- search_path.extend(sage_data_path("reflexive_polytopes"))
295
+ search_path.extend(sage_data_paths("reflexive_polytopes"))
290
296
 
291
297
  dirname = "Full3d"
292
298
  if name == "polytopes_db_4d":
293
299
  dirname = "Hodge4d"
294
300
 
295
- StaticFile.__init__(self, name,
296
- filename=dirname,
297
- search_path=search_path)
301
+ StaticFile.__init__(self, name, filename=dirname, search_path=search_path)
298
302
 
299
303
 
300
304
  def all_features():
301
- return [PythonModule('conway_polynomials', spkg='conway_polynomials', type='standard'),
302
- DatabaseCremona(),
303
- DatabaseCremona('cremona_mini', type='standard'),
304
- DatabaseEllcurves(),
305
- DatabaseGraphs(),
306
- DatabaseJones(),
307
- DatabaseKnotInfo(),
308
- DatabaseMatroids(),
309
- DatabaseCubicHecke(),
310
- DatabaseReflexivePolytopes(),
311
- DatabaseReflexivePolytopes('polytopes_db_4d')]
305
+ return [
306
+ PythonModule("conway_polynomials", spkg="conway_polynomials", type="standard"),
307
+ DatabaseCremona(),
308
+ DatabaseCremona("cremona_mini", type="standard"),
309
+ DatabaseEllcurves(),
310
+ DatabaseGraphs(),
311
+ DatabaseJones(),
312
+ DatabaseKnotInfo(),
313
+ DatabaseMatroids(),
314
+ DatabaseCubicHecke(),
315
+ DatabaseReflexivePolytopes(),
316
+ DatabaseReflexivePolytopes("polytopes_db_4d"),
317
+ ]
sage/features/fricas.py CHANGED
@@ -12,10 +12,10 @@ Features for testing the presence of ``fricas``
12
12
  # https://www.gnu.org/licenses/
13
13
  # *****************************************************************************
14
14
 
15
- import os
16
15
  import subprocess
17
16
  from . import Executable, FeatureTestResult, PythonModule
18
17
  from .join_feature import JoinFeature
18
+ from packaging.version import Version
19
19
 
20
20
 
21
21
  class FriCAS(Executable):
@@ -28,6 +28,8 @@ class FriCAS(Executable):
28
28
  sage: FriCAS().is_present() # optional - fricas
29
29
  FeatureTestResult('fricas_executable', True)
30
30
  """
31
+ MINIMUM_VERSION = "1.3.8"
32
+
31
33
  def __init__(self):
32
34
  r"""
33
35
  TESTS::
@@ -40,6 +42,23 @@ class FriCAS(Executable):
40
42
  executable='fricas',
41
43
  url='https://fricas.github.io')
42
44
 
45
+ def get_version(self):
46
+ r"""
47
+ Retrieve the installed FriCAS version
48
+
49
+ EXAMPLES::
50
+ sage: from sage.features.fricas import FriCAS
51
+ sage: FriCAS().get_version() # optional - fricas
52
+ '1.3...'
53
+ """
54
+ try:
55
+ output = subprocess.check_output(['fricas', '--version'], stderr=subprocess.STDOUT)
56
+ version_line = output.decode('utf-8').strip()
57
+ version = version_line.split()[1]
58
+ return version
59
+ except subprocess.CalledProcessError:
60
+ return None
61
+
43
62
  def is_functional(self):
44
63
  r"""
45
64
  Check whether ``fricas`` works on trivial input.
@@ -55,14 +74,24 @@ class FriCAS(Executable):
55
74
  lines = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
56
75
  except subprocess.CalledProcessError as e:
57
76
  return FeatureTestResult(self, False,
58
- reason="Call `{command}` failed with exit code {e.returncode}".format(command=" ".join(command), e=e))
77
+ reason="Call `{command}` failed with exit code {e.returncode}".format(command=" ".join(command), e=e))
59
78
 
60
79
  expected = b"FriCAS"
61
80
  if lines.find(expected) == -1:
62
81
  return FeatureTestResult(self, False,
63
- reason="Call `{command}` did not produce output which contains `{expected}`".format(command=" ".join(command), expected=expected))
82
+ reason="Call `{command}` did not produce output which contains `{expected}`".format(command=" ".join(command),
83
+ expected=expected))
84
+ version = self.get_version()
85
+ if version is None:
86
+ return FeatureTestResult(self, False,
87
+ reason="Could not determine FriCAS version")
64
88
 
65
- return FeatureTestResult(self, True)
89
+ try:
90
+ if Version(version) < Version(self.MINIMUM_VERSION):
91
+ return FeatureTestResult(self, False, reason=f"FriCAS version {version} is too old; minimum required is {self.MINIMUM_VERSION}")
92
+ return FeatureTestResult(self, True)
93
+ except ValueError:
94
+ return FeatureTestResult(self, False, reason="Invalid Version Format")
66
95
 
67
96
 
68
97
  def all_features():
sage/features/giac.py CHANGED
@@ -26,11 +26,11 @@ class Giac(Executable):
26
26
  True
27
27
  """
28
28
  Executable.__init__(self, 'giac_executable', executable='giac',
29
- spkg='giac', type='standard')
29
+ spkg='giac', type='optional')
30
30
 
31
31
 
32
32
  def all_features():
33
33
  return [JoinFeature("giac",
34
34
  (Giac(),
35
35
  PythonModule('sage.interfaces.giac')),
36
- spkg='sagemath_giac', type='standard')]
36
+ spkg='sagemath_giac', type='optional')]
sage/features/latex.py CHANGED
@@ -242,7 +242,7 @@ class TeXFile(StaticFile):
242
242
  sage: feature.absolute_filename() # optional - latex
243
243
  '.../latex/base/article.cls'
244
244
  """
245
- from subprocess import run, CalledProcessError, PIPE
245
+ from subprocess import run, CalledProcessError
246
246
  try:
247
247
  proc = run(['kpsewhich', self.filename],
248
248
  capture_output=True, text=True, check=True)
sage/features/latte.py CHANGED
@@ -59,7 +59,7 @@ class Latte_integrate(Executable):
59
59
 
60
60
  class Latte(JoinFeature):
61
61
  r"""
62
- A :class:`~sage.features.Feature` describing the presence of excecutables
62
+ A :class:`~sage.features.Feature` describing the presence of executables
63
63
  from :ref:`LattE integrale <spkg_latte_int>`.
64
64
 
65
65
  EXAMPLES::
@@ -0,0 +1,45 @@
1
+ # sage_setup: distribution = sagemath-environment
2
+ r"""
3
+ Feature for testing if Meson editable install is used.
4
+ """
5
+ from . import Feature, FeatureTestResult
6
+
7
+
8
+ class MesonEditable(Feature):
9
+ r"""
10
+ A :class:`~sage.features.Feature` describing if Meson editable install
11
+ is used.
12
+
13
+ EXAMPLES::
14
+
15
+ sage: from sage.features.meson_editable import MesonEditable
16
+ sage: MesonEditable()
17
+ Feature('meson_editable')
18
+ """
19
+ def __init__(self):
20
+ r"""
21
+ TESTS::
22
+
23
+ sage: from sage.features.meson_editable import MesonEditable
24
+ sage: MesonEditable() is MesonEditable()
25
+ True
26
+ """
27
+ Feature.__init__(self, 'meson_editable')
28
+
29
+ def _is_present(self):
30
+ r"""
31
+ Test whether Meson editable install is used.
32
+
33
+ EXAMPLES::
34
+
35
+ sage: from sage.features.meson_editable import MesonEditable
36
+ sage: MesonEditable()._is_present() # random
37
+ FeatureTestResult('meson_editable', True)
38
+ """
39
+ import sage
40
+ result = type(sage.__loader__).__module__ == '_sagemath_editable_loader'
41
+ return FeatureTestResult(self, result)
42
+
43
+
44
+ def all_features():
45
+ return [MesonEditable()]
@@ -69,7 +69,7 @@ class PackageSystem(Feature):
69
69
  sage: fedora.spkg_installation_hint('openblas') # optional - SAGE_ROOT
70
70
  'To install openblas using the fedora package manager, you can try to run:\n!sudo yum install openblas-devel'
71
71
  """
72
- from subprocess import run, CalledProcessError, PIPE
72
+ from subprocess import run, CalledProcessError
73
73
  lines = []
74
74
  system = self.name
75
75
  try:
sage/features/sagemath.py CHANGED
@@ -532,7 +532,7 @@ class sage__libs__giac(JoinFeature):
532
532
  """
533
533
  JoinFeature.__init__(self, 'sage.libs.giac',
534
534
  [PythonModule('sage.libs.giac.giac')],
535
- spkg='sagemath_giac', type='standard')
535
+ spkg='sagemath_giac', type='optional')
536
536
 
537
537
 
538
538
  class sage__libs__homfly(JoinFeature):
sage/misc/package_dir.py CHANGED
@@ -262,6 +262,7 @@ def is_package_or_sage_namespace_package_dir(path, *, distribution_filter=None):
262
262
 
263
263
  :mod:`sage.cpython` is an ordinary package::
264
264
 
265
+ sage: # optional - !meson_editable
265
266
  sage: from sage.misc.package_dir import is_package_or_sage_namespace_package_dir
266
267
  sage: len(sage.cpython.__path__)
267
268
  1
@@ -273,6 +274,7 @@ def is_package_or_sage_namespace_package_dir(path, *, distribution_filter=None):
273
274
  :mod:`sage.libs.mpfr` only has an ``__init__.pxd`` file, but we consider
274
275
  it a package directory for consistency with Cython::
275
276
 
277
+ sage: # optional - !meson_editable
276
278
  sage: directories = [os.path.join(p, 'mpfr')
277
279
  ....: for p in sage.libs.__path__]; directories
278
280
  ['.../sage/libs/mpfr'...]
@@ -281,6 +283,7 @@ def is_package_or_sage_namespace_package_dir(path, *, distribution_filter=None):
281
283
 
282
284
  :mod:`sage` is an implicit namespace package::
283
285
 
286
+ sage: # optional - !meson_editable
284
287
  sage: sage.__path__[0]
285
288
  '.../sage'
286
289
  sage: all(is_package_or_sage_namespace_package_dir(p) for p in sage.__path__)
@@ -288,12 +291,34 @@ def is_package_or_sage_namespace_package_dir(path, *, distribution_filter=None):
288
291
 
289
292
  Not a package::
290
293
 
294
+ sage: # optional - !meson_editable
291
295
  sage: directories = [os.path.join(p, 'ginac') # needs sage.symbolic
292
296
  ....: for p in sage.symbolic.__path__]; directories
293
297
  ['.../sage/symbolic/ginac'...]
294
298
  sage: any(is_package_or_sage_namespace_package_dir(d) # needs sage.symbolic
295
299
  ....: for d in directories)
296
300
  False
301
+
302
+ TESTS::
303
+
304
+ sage: # optional - meson_editable
305
+ sage: from sage.misc.package_dir import is_package_or_sage_namespace_package_dir
306
+ sage: directory = os.path.dirname(sage.cpython.__file__); directory
307
+ '.../sage/cpython'
308
+ sage: is_package_or_sage_namespace_package_dir(directory)
309
+ True
310
+
311
+ sage: # optional - meson_editable
312
+ sage: directory = os.path.join(os.path.dirname(sage.libs.__file__), 'mpfr'); directory
313
+ '.../sage/libs/mpfr'
314
+ sage: is_package_or_sage_namespace_package_dir(directory)
315
+ True
316
+
317
+ sage: # optional - meson_editable, sage.symbolic
318
+ sage: directory = os.path.join(os.path.dirname(sage.symbolic.__file__), 'ginac'); directory
319
+ '.../sage/symbolic/ginac'
320
+ sage: is_package_or_sage_namespace_package_dir(directory)
321
+ False
297
322
  """
298
323
  if os.path.exists(os.path.join(path, '__init__.py')): # ordinary package
299
324
  return True
@@ -351,8 +376,15 @@ def walk_packages(path=None, prefix='', onerror=None):
351
376
 
352
377
  EXAMPLES::
353
378
 
379
+ sage: # optional - !meson_editable
354
380
  sage: sorted(sage.misc.package_dir.walk_packages(sage.misc.__path__)) # a namespace package
355
381
  [..., ModuleInfo(module_finder=FileFinder('.../sage/misc'), name='package_dir', ispkg=False), ...]
382
+
383
+ TESTS::
384
+
385
+ sage: # optional - meson_editable
386
+ sage: sorted(sage.misc.package_dir.walk_packages(sage.misc.__path__))
387
+ [..., ModuleInfo(module_finder=<...MesonpyPathFinder object...>, name='package_dir', ispkg=False), ...]
356
388
  """
357
389
  # Adapted from https://github.com/python/cpython/blob/3.11/Lib/pkgutil.py
358
390
 
@@ -376,9 +408,9 @@ def walk_packages(path=None, prefix='', onerror=None):
376
408
  yielded[name] = 1
377
409
  yield ModuleInfo(i, name, ispkg)
378
410
 
379
- def iter_importer_modules(importer, prefix=''):
411
+ def _iter_importer_modules_helper(importer, prefix=''):
380
412
  r"""
381
- Yield :class:`ModuleInfo` for all modules of ``importer``.
413
+ Helper function for :func:`iter_importer_modules`.
382
414
  """
383
415
  from importlib.machinery import FileFinder
384
416
 
@@ -397,11 +429,6 @@ def walk_packages(path=None, prefix='', onerror=None):
397
429
 
398
430
  for fn in filenames:
399
431
  modname = inspect.getmodulename(fn)
400
- if modname and (modname in ['__init__', 'all']
401
- or modname.startswith('all__')
402
- or modname in yielded):
403
- continue
404
-
405
432
  path = os.path.join(importer.path, fn)
406
433
  ispkg = False
407
434
 
@@ -420,6 +447,18 @@ def walk_packages(path=None, prefix='', onerror=None):
420
447
  else:
421
448
  yield from importer.iter_modules(prefix)
422
449
 
450
+ def iter_importer_modules(importer, prefix=''):
451
+ r"""
452
+ Yield :class:`ModuleInfo` for all modules of ``importer``.
453
+ """
454
+ for name, ispkg in sorted(_iter_importer_modules_helper(importer, prefix)):
455
+ # we sort again for consistency of output ordering if importer is not
456
+ # a FileFinder (needed in doctest of :func:`sage.misc.dev_tools/load_submodules`)
457
+ modname = name.rsplit('.', 1)[-1]
458
+ if modname in ['__init__', 'all'] or modname.startswith('all__'):
459
+ continue
460
+ yield name, ispkg
461
+
423
462
  def seen(p, m={}):
424
463
  if p in m:
425
464
  return True
sage/version.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # sage_setup: distribution = sagemath-environment
2
2
  # Sage version information for Python scripts
3
- # This file is auto-generated by the sage-update-version script, do not edit!
4
- version = '10.5.43'
5
- date = '2025-06-19'
6
- banner = 'passagemath version 10.5.43, Release Date: 2025-06-19'
3
+ # This file is auto-generated by the update-version script, do not edit!
4
+ version = '10.6.1.rc2'
5
+ date = '2025-06-24'
6
+ banner = 'passagemath version 10.6.1.rc2, Release Date: 2025-06-24'
@@ -1,9 +0,0 @@
1
- # Sage version information for shell scripts.
2
- #
3
- # #31049: The following line is valid shell code but not valid Python code,
4
- # which stops "setup.py develop" from rewriting it as a Python file.
5
- :
6
- # This file is auto-generated by the sage-update-version script, do not edit!
7
- SAGE_VERSION='10.5.43'
8
- SAGE_RELEASE_DATE='2025-06-19'
9
- SAGE_VERSION_BANNER='passagemath version 10.5.43, Release Date: 2025-06-19'