Skip to content

Commit f98985b

Browse files
author
Release Manager
committed
gh-40894: Remove usage of `SAGE_SHARE` from sagelib The `SAGE_SHARE` variable is still used in sagelib to manage some data files. This is problematic for a few reasons: - `SAGE_SHARE` can only store a single path, but data can be installed in multiple different paths (eg. system vs user paths) - Some methods try to write there, which is not possible if the path is not writeable (as it is the case on distro packages, where `SAGE_SHARE` generally points to `/usr/share`) We replace all uses in sagelib with more appropriate solutions. For locating data files, we use `sage_data_paths`, which on Linux includes in particular `XDG_DATA_DIRS`. When writing files we always use a user path under `DOT_SAGE`, which is the only one we can assume to be writeable. `SAGE_SHARE` is still used as a fallback value for `sage_data_paths`, so this should be backwards compatible. URL: #40894 Reported by: Antonio Rojas Reviewer(s): Antonio Rojas, Tobias Diez
2 parents 7c7db5e + b8c3e25 commit f98985b

File tree

17 files changed

+110
-98
lines changed

17 files changed

+110
-98
lines changed

pkgs/sage-conf/_sage_conf/_conf.py.in

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ VERSION = "@PACKAGE_VERSION@"
88
# to it.
99
SAGE_LOCAL = "@prefix@"
1010
SAGE_ROOT = "@SAGE_ROOT@"
11-
SAGE_SHARE = "@SAGE_SHARE@"
1211

1312
# The semicolon-separated list of GAP root paths. This is the list of
1413
# locations that are searched for GAP packages. This is passed directly

src/sage/combinat/cluster_algebra_quiver/mutation_type.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,30 +1257,30 @@ def load_data(n: int, user=True) -> dict:
12571257
We test data from the ``database_mutation_class`` optional package::
12581258
12591259
sage: load_data(2, user=False) # optional - database_mutation_class
1260-
{('G', 2): [('AO', (((0, 1), (1, -3)), )), ('AO', (((0, 1), (3, -1)), ))]}
1260+
{('G', 2): [('AO', (((0, 1), (1, -3)),)), ('AO', (((0, 1), (3, -1)),))]}
12611261
sage: D = load_data(3, user=False) # optional - database_mutation_class
12621262
sage: sorted(D.items()) # optional - database_mutation_class
12631263
[(('G', 2, -1),
1264-
[('BH?', (((1, 2), (1, -3)), )),
1265-
('BGO', (((2, 1), (3, -1)), )),
1266-
('BW?', (((0, 1), (3, -1)), )),
1267-
('BP?', (((0, 1), (1, -3)), )),
1264+
[('BH?', (((1, 2), (1, -3)),)),
1265+
('BGO', (((2, 1), (3, -1)),)),
1266+
('BW?', (((0, 1), (3, -1)),)),
1267+
('BP?', (((0, 1), (1, -3)),)),
12681268
('BP_', (((0, 1), (1, -3)), ((2, 0), (3, -1)))),
12691269
('BP_', (((0, 1), (3, -1)), ((1, 2), (1, -3)), ((2, 0), (2, -2))))]),
12701270
(('G', 2, 1),
1271-
[('BH?', (((1, 2), (3, -1)), )),
1272-
('BGO', (((2, 1), (1, -3)), )),
1273-
('BW?', (((0, 1), (1, -3)), )),
1274-
('BP?', (((0, 1), (3, -1)), )),
1271+
[('BH?', (((1, 2), (3, -1)),)),
1272+
('BGO', (((2, 1), (1, -3)),)),
1273+
('BW?', (((0, 1), (1, -3)),)),
1274+
('BP?', (((0, 1), (3, -1)),)),
12751275
('BKO', (((1, 0), (3, -1)), ((2, 1), (1, -3)))),
12761276
('BP_', (((0, 1), (2, -2)), ((1, 2), (1, -3)), ((2, 0), (3, -1))))])]
12771277
"""
1278-
from sage.env import DOT_SAGE, SAGE_SHARE
1278+
from sage.env import DOT_SAGE, sage_data_paths
12791279

12801280
# we check
12811281
# - if the data is stored by the user, and if this is not the case
12821282
# - if the data is stored by the optional package install
1283-
paths = [Path(SAGE_SHARE)]
1283+
paths = [Path(path) for path in sage_data_paths()]
12841284
if user:
12851285
paths.append(Path(DOT_SAGE))
12861286
data = {}

src/sage/databases/all.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
sage: oeis
3535
The On-Line Encyclopedia of Integer Sequences (https://oeis.org/)
3636
37-
sage: SymbolicData()
37+
sage: SymbolicData() # optional - database_symbolic_data
3838
SymbolicData with ... ideals
3939
"""
4040

src/sage/databases/cremona.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
This causes the latest version of the database to be downloaded from
2121
the internet.
2222
23-
Both the mini and full versions of John Cremona's tables are stored in
24-
SAGE_SHARE/cremona as SQLite databases. The mini version has the layout::
23+
Both the mini and full versions of John Cremona's tables are stored
24+
as SQLite databases. The mini version has the layout::
2525
2626
CREATE TABLE t_class(conductor INTEGER, class TEXT PRIMARY KEY, rank INTEGER);
2727
CREATE TABLE t_curve(class TEXT, curve TEXT PRIMARY KEY, eqn TEXT UNIQUE, tors INTEGER);
@@ -115,8 +115,8 @@ def build(name, data_tgz, largest_conductor=0, mini=False, decompress=True):
115115
116116
sage: d = sage.databases.cremona.build('cremona','ecdata.tgz') # not tested
117117
"""
118-
from sage.env import SAGE_SHARE
119-
db_path = os.path.join(SAGE_SHARE,'cremona',name.replace(' ','_')+'.db')
118+
from sage.env import DOT_SAGE
119+
db_path = os.path.join(DOT_SAGE, 'db', 'cremona', name.replace(' ','_')+'.db')
120120
if os.path.exists(db_path):
121121
raise RuntimeError('Please (re)move %s before building ' % db_path
122122
+ 'database')

src/sage/databases/cunningham_tables.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
from sage.misc.cachefunc import cached_function
2020
from sage.rings.integer import Integer
2121
from sage.misc.persist import load
22-
from sage.env import SAGE_SHARE
22+
from sage.env import sage_data_paths
2323

2424

2525
@cached_function
@@ -43,11 +43,11 @@ def cunningham_prime_factors():
4343
17,
4444
...
4545
"""
46-
file = os.path.join(SAGE_SHARE,'cunningham_tables','cunningham_prime_factors.sobj')
47-
if os.path.exists(file):
48-
return [Integer(_) for _ in load(file)]
49-
else:
50-
from warnings import warn
51-
warn("You might consider installing the optional package for factoring Cunningham numbers"
52-
" with the following command: ``sage -i cunningham_tables``")
53-
return []
46+
for path in sage_data_paths('cunningham_tables'):
47+
file = os.path.join(path, 'cunningham_prime_factors.sobj')
48+
if os.path.exists(file):
49+
return [Integer(_) for _ in load(file)]
50+
51+
from warnings import warn
52+
warn("The optional cunningham_tables package for factoring Cunningham numbers is not installed")
53+
return []

src/sage/databases/db_modular_polynomials.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
# https://www.gnu.org/licenses/
3333
# ****************************************************************************
3434
import bz2
35+
import os
3536
from pathlib import Path
3637

3738

@@ -52,14 +53,14 @@ def _dbz_to_string(name) -> str:
5253
sage: _dbz_to_string('PolHeeg/Cls/0000001-0005000/pol.0000003.dbz')
5354
'0\n1\n'
5455
"""
55-
from sage.env import SAGE_SHARE
56-
filename = Path(SAGE_SHARE) / 'kohel' / name
57-
try:
58-
with open(filename, 'rb') as f:
59-
data = bz2.decompress(f.read())
60-
except OSError:
61-
raise FileNotFoundError('file not found in the Kohel database')
62-
return data.decode()
56+
from sage.env import sage_data_paths
57+
for path in sage_data_paths('kohel'):
58+
filename = Path(path) / name
59+
if os.path.exists(filename):
60+
with open(filename, 'rb') as f:
61+
data = bz2.decompress(f.read())
62+
return data.decode()
63+
raise FileNotFoundError('file not found in the Kohel database')
6364

6465

6566
def _dbz_to_integer_list(name) -> list[list]:

src/sage/databases/jones.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@
7373
from sage.rings.rational_field import RationalField
7474
from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
7575
from sage.combinat.subset import powerset
76-
from sage.env import SAGE_SHARE
7776

7877
from sage.misc.persist import load, save
7978

src/sage/databases/odlyzko.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import os
3030

3131
from sage.misc.persist import load
32-
from sage.env import SAGE_SHARE
32+
from sage.env import sage_data_paths
3333

3434

3535
def zeta_zeros():
@@ -54,6 +54,9 @@ def zeta_zeros():
5454
2001052
5555
"""
5656
from sage.misc.verbose import verbose
57-
sobj = os.path.join(SAGE_SHARE, 'odlyzko', 'zeros.sobj')
58-
verbose("Loading Odlyzko database from " + sobj)
59-
return load(sobj)
57+
for path in sage_data_paths('odlyzko'):
58+
sobj = os.path.join(path, 'zeros.sobj')
59+
if os.path.exists(sobj):
60+
verbose("Loading Odlyzko database from " + sobj)
61+
return load(sobj)
62+
raise FileNotFoundError('Could not find the odlyzko database')

src/sage/databases/sloane.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# sage.doctest: needs sloane_database
12
"""
23
Local copy of the On-Line Encyclopedia of Integer Sequences
34
@@ -11,29 +12,29 @@
1112
1213
::
1314
14-
sage: SloaneEncyclopedia[60843] # optional - sloane_database
15+
sage: SloaneEncyclopedia[60843]
1516
[1, 6, 21, 107, 47176870]
1617
1718
To get the name of a sequence, type
1819
1920
::
2021
21-
sage: SloaneEncyclopedia.sequence_name(1) # optional - sloane_database
22+
sage: SloaneEncyclopedia.sequence_name(1)
2223
'Number of groups of order n.'
2324
2425
To search locally for a particular subsequence, type
2526
2627
::
2728
28-
sage: SloaneEncyclopedia.find([1,2,3,4,5], 1) # optional - sloane_database
29+
sage: SloaneEncyclopedia.find([1,2,3,4,5], 1)
2930
[(15, [1, 2, 3, 4, 5, 7, 7, 8, 9, 11, 11, 13, 13, 16, 16, 16, 17, 19, 19, 23, 23, 23, 23, 25, 25, 27, 27, 29, 29, 31, 31, 32, 37, 37, 37, 37, 37, 41, 41, 41, 41, 43, 43, 47, 47, 47, 47, 49, 49, 53, 53, 53, 53, 59, 59, 59, 59, 59, 59, 61, 61, 64, 64, 64, 67, 67, 67, 71, 71, 71, 71, 73])]
3031
3132
The default maximum number of results is 30, but to return up to
3233
100, type
3334
3435
::
3536
36-
sage: SloaneEncyclopedia.find([1,2,3,4,5], 100) # optional - sloane_database
37+
sage: SloaneEncyclopedia.find([1,2,3,4,5], 100)
3738
[(15, [1, 2, 3, 4, 5, 7, 7, 8, 9, 11, 11, ...
3839
3940
Results in either case are of the form [ (number, list) ].
@@ -87,7 +88,7 @@
8788
import ssl
8889

8990
from sage.misc.verbose import verbose
90-
from sage.env import SAGE_SHARE
91+
from sage.env import DOT_SAGE, sage_data_paths
9192
from sage.rings.integer_ring import ZZ
9293

9394

@@ -101,7 +102,12 @@ def __init__(self):
101102
"""
102103
Initialize the database but do not load any of the data.
103104
"""
104-
self.__path__ = os.path.join(SAGE_SHARE, 'sloane')
105+
self.__path__ = os.path.join(DOT_SAGE, 'db', 'sloane')
106+
for path in sage_data_paths('sloane'):
107+
file_oeis = os.path.join(path, 'sloane-oeis.bz2')
108+
file_names = os.path.join(path, 'sloane-names.bz2')
109+
if os.path.exists(file_oeis) and os.path.exists(file_names):
110+
self.__path__ = path
105111
self.__file__ = os.path.join(self.__path__, 'sloane-oeis.bz2')
106112
self.__file_names__ = os.path.join(self.__path__, 'sloane-names.bz2')
107113
self.__loaded__ = False
@@ -155,7 +161,7 @@ def is_installed(self):
155161
156162
EXAMPLES::
157163
158-
sage: SloaneEncyclopedia.is_installed() # optional - sloane_database
164+
sage: SloaneEncyclopedia.is_installed()
159165
True
160166
"""
161167
return os.path.exists(self.__file__) and os.path.exists(self.__file_names__)
@@ -333,7 +339,7 @@ def sequence_name(self, N):
333339
334340
EXAMPLES::
335341
336-
sage: SloaneEncyclopedia.sequence_name(1) # optional - sloane_database
342+
sage: SloaneEncyclopedia.sequence_name(1)
337343
'Number of groups of order n.'
338344
"""
339345
self.load()

src/sage/databases/stein_watkins.py

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# sage.doctest: needs database_stein_watkins
12
r"""
23
The Stein-Watkins table of elliptic curves
34
@@ -41,7 +42,6 @@
4142
We type ``next(d)`` to get each isogeny class of
4243
curves from ``d``::
4344
44-
sage: # optional - database_stein_watkins
4545
sage: C = next(d)
4646
sage: C
4747
Stein-Watkins isogeny class of conductor 11
@@ -56,7 +56,6 @@
5656
5757
::
5858
59-
sage: # optional - database_stein_watkins
6059
sage: C.data
6160
['11', '[11]', '0', '0.253842', '25', '+*1']
6261
sage: C.curves
@@ -83,24 +82,23 @@
8382
following::
8483
8584
sage: d = SteinWatkinsAllData(1)
86-
sage: C = next(d) # optional - database_stein_watkins
87-
sage: C # optional - database_stein_watkins
85+
sage: C = next(d)
86+
sage: C
8887
Stein-Watkins isogeny class of conductor 100002
89-
sage: C.curves # optional - database_stein_watkins
88+
sage: C.curves
9089
[[[1, 1, 0, 112, 0], '(8,1,2,1)', 'X', '2'],
9190
[[1, 1, 0, -448, -560], '[4,2,1,2]', 'X', '2']]
9291
9392
Next we access the prime-conductor data::
9493
9594
sage: d = SteinWatkinsPrimeData(0)
96-
sage: C = next(d) # optional - database_stein_watkins
97-
sage: C # optional - database_stein_watkins
95+
sage: C = next(d)
96+
sage: C
9897
Stein-Watkins isogeny class of conductor 11
9998
10099
Each call ``next(d)`` gives another elliptic curve of
101100
prime conductor::
102101
103-
sage: # optional - database_stein_watkins
104102
sage: C = next(d)
105103
sage: C
106104
Stein-Watkins isogeny class of conductor 17
@@ -137,7 +135,7 @@
137135
import bz2
138136
import os
139137

140-
from sage.env import SAGE_SHARE
138+
from sage.env import sage_data_paths
141139

142140

143141
class SteinWatkinsIsogenyClass:
@@ -183,7 +181,13 @@ def __init__(self, num):
183181
raise RuntimeError("num (=%s) must be a nonnegative integer" % num)
184182
name = str(num)
185183
name = '0' * (3 - len(name)) + name
186-
self._file = os.path.join(SAGE_SHARE, 'stein_watkins', 'a.%s.bz2' % name)
184+
self._file = None
185+
for path in sage_data_paths('stein_watkins'):
186+
file = os.path.join(path, 'a.%s.bz2' % name)
187+
if os.path.exists(file):
188+
self._file = file
189+
if not self._file:
190+
raise FileNotFoundError('Could not find the Stein-Watkins database')
187191
self._iter = iter(self)
188192

189193
def __repr__(self):
@@ -201,8 +205,8 @@ def __iter__(self):
201205
EXAMPLES::
202206
203207
sage: d = SteinWatkinsAllData(0)
204-
sage: d = d[10:20] # optional - database_stein_watkins; long time
205-
sage: for C in d: # optional - database_stein_watkins; long time
208+
sage: d = d[10:20]
209+
sage: for C in d:
206210
....: print(C)
207211
Stein-Watkins isogeny class of conductor 11
208212
Stein-Watkins isogeny class of conductor 14
@@ -250,7 +254,7 @@ def __getitem__(self, N):
250254
EXAMPLES::
251255
252256
sage: d = SteinWatkinsAllData(0)
253-
sage: d[15:18] # optional - database_stein_watkins; long time
257+
sage: d[15:18]
254258
[Stein-Watkins isogeny class of conductor 15, Stein-Watkins isogeny
255259
class of conductor 17]
256260
"""
@@ -281,12 +285,12 @@ def iter_levels(self):
281285
282286
sage: d = SteinWatkinsAllData(1)
283287
sage: E = d.iter_levels()
284-
sage: next(E) # optional - database_stein_watkins
288+
sage: next(E)
285289
[Stein-Watkins isogeny class of conductor 100002]
286-
sage: next(E) # optional - database_stein_watkins
290+
sage: next(E)
287291
[Stein-Watkins isogeny class of conductor 100005,
288292
Stein-Watkins isogeny class of conductor 100005]
289-
sage: next(E) # optional - database_stein_watkins
293+
sage: next(E)
290294
[Stein-Watkins isogeny class of conductor 100007]
291295
"""
292296
it = iter(self)
@@ -317,7 +321,13 @@ def __init__(self, num):
317321
raise RuntimeError("num (=%s) must be a nonnegative integer" % num)
318322
name = str(num)
319323
name = '0' * (2 - len(name)) + name
320-
self._file = os.path.join(SAGE_SHARE, 'stein_watkins', 'p.%s.bz2' % name)
324+
self._file = None
325+
for path in sage_data_paths('stein_watkins'):
326+
file = os.path.join(path, 'p.%s.bz2' % name)
327+
if os.path.exists(file):
328+
self._file = file
329+
if not self._file:
330+
raise FileNotFoundError('Could not find the Stein-Watkins database')
321331
self._iter = iter(self)
322332

323333
def __repr__(self):
@@ -338,7 +348,7 @@ def ecdb_num_curves(max_level=200000):
338348
339349
EXAMPLES::
340350
341-
sage: sage.databases.stein_watkins.ecdb_num_curves(100) # optional - database_stein_watkins
351+
sage: sage.databases.stein_watkins.ecdb_num_curves(100)
342352
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 6, 8, 0, 4, 0, 3, 4, 6, 0, 0,
343353
6, 0, 5, 4, 0, 0, 8, 0, 4, 4, 4, 3, 4, 4, 5, 4, 4, 0, 6, 1, 2, 8, 2, 0,
344354
6, 4, 8, 2, 2, 1, 6, 4, 6, 7, 3, 0, 0, 1, 4, 6, 4, 2, 12, 1, 0, 2, 4, 0,

0 commit comments

Comments
 (0)