passagemath-environment 10.4.1__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 (70) hide show
  1. passagemath_environment-10.4.1.data/scripts/sage +1140 -0
  2. passagemath_environment-10.4.1.data/scripts/sage-env +667 -0
  3. passagemath_environment-10.4.1.data/scripts/sage-num-threads.py +105 -0
  4. passagemath_environment-10.4.1.data/scripts/sage-python +2 -0
  5. passagemath_environment-10.4.1.data/scripts/sage-venv-config +42 -0
  6. passagemath_environment-10.4.1.data/scripts/sage-version.sh +9 -0
  7. passagemath_environment-10.4.1.dist-info/METADATA +76 -0
  8. passagemath_environment-10.4.1.dist-info/RECORD +70 -0
  9. passagemath_environment-10.4.1.dist-info/WHEEL +5 -0
  10. passagemath_environment-10.4.1.dist-info/top_level.txt +1 -0
  11. sage/all__sagemath_environment.py +4 -0
  12. sage/env.py +496 -0
  13. sage/features/__init__.py +981 -0
  14. sage/features/all.py +126 -0
  15. sage/features/bliss.py +85 -0
  16. sage/features/cddlib.py +38 -0
  17. sage/features/coxeter3.py +45 -0
  18. sage/features/csdp.py +83 -0
  19. sage/features/cython.py +38 -0
  20. sage/features/databases.py +302 -0
  21. sage/features/dvipng.py +40 -0
  22. sage/features/ecm.py +42 -0
  23. sage/features/ffmpeg.py +119 -0
  24. sage/features/four_ti_2.py +55 -0
  25. sage/features/fricas.py +66 -0
  26. sage/features/gap.py +86 -0
  27. sage/features/gfan.py +38 -0
  28. sage/features/giac.py +30 -0
  29. sage/features/graph_generators.py +171 -0
  30. sage/features/graphviz.py +117 -0
  31. sage/features/igraph.py +44 -0
  32. sage/features/imagemagick.py +138 -0
  33. sage/features/interfaces.py +256 -0
  34. sage/features/internet.py +65 -0
  35. sage/features/jmol.py +44 -0
  36. sage/features/join_feature.py +146 -0
  37. sage/features/kenzo.py +77 -0
  38. sage/features/latex.py +300 -0
  39. sage/features/latte.py +85 -0
  40. sage/features/lrs.py +164 -0
  41. sage/features/mcqd.py +45 -0
  42. sage/features/meataxe.py +46 -0
  43. sage/features/mip_backends.py +114 -0
  44. sage/features/msolve.py +68 -0
  45. sage/features/nauty.py +70 -0
  46. sage/features/normaliz.py +43 -0
  47. sage/features/palp.py +65 -0
  48. sage/features/pandoc.py +42 -0
  49. sage/features/pdf2svg.py +41 -0
  50. sage/features/phitigra.py +42 -0
  51. sage/features/pkg_systems.py +195 -0
  52. sage/features/polymake.py +43 -0
  53. sage/features/poppler.py +58 -0
  54. sage/features/rubiks.py +180 -0
  55. sage/features/sagemath.py +1205 -0
  56. sage/features/sat.py +103 -0
  57. sage/features/singular.py +48 -0
  58. sage/features/sirocco.py +45 -0
  59. sage/features/sphinx.py +71 -0
  60. sage/features/standard.py +38 -0
  61. sage/features/symengine_py.py +44 -0
  62. sage/features/tdlib.py +38 -0
  63. sage/features/threejs.py +75 -0
  64. sage/features/topcom.py +67 -0
  65. sage/misc/all__sagemath_environment.py +2 -0
  66. sage/misc/package.py +570 -0
  67. sage/misc/package_dir.py +621 -0
  68. sage/misc/temporary_file.py +546 -0
  69. sage/misc/viewer.py +369 -0
  70. sage/version.py +5 -0
sage/features/gap.py ADDED
@@ -0,0 +1,86 @@
1
+ # sage_setup: distribution = sagemath-environment
2
+ r"""
3
+ Features for testing the presence of the SageMath interfaces to ``gap`` and of GAP packages
4
+ """
5
+ # *****************************************************************************
6
+ # Copyright (C) 2016 Julian Rüth
7
+ # 2018 Jeroen Demeyer
8
+ #
9
+ # Distributed under the terms of the GNU General Public License (GPL)
10
+ # as published by the Free Software Foundation; either version 2 of
11
+ # the License, or (at your option) any later version.
12
+ # https://www.gnu.org/licenses/
13
+ # *****************************************************************************
14
+
15
+ from . import Feature, FeatureTestResult, PythonModule
16
+ from .join_feature import JoinFeature
17
+ from .sagemath import sage__libs__gap
18
+
19
+ class GapPackage(Feature):
20
+ r"""
21
+ A :class:`~sage.features.Feature` describing the presence of a GAP package.
22
+
23
+ A GAP package is "present" if it *can be* loaded, not if it *has
24
+ been* loaded.
25
+
26
+ .. SEEALSO::
27
+
28
+ :class:`Feature sage.libs.gap <~sage.features.sagemath.sage__libs__gap>`
29
+
30
+ EXAMPLES::
31
+
32
+ sage: from sage.features.gap import GapPackage
33
+ sage: GapPackage("grape", spkg='gap_packages')
34
+ Feature('gap_package_grape')
35
+ """
36
+ def __init__(self, package, **kwds):
37
+ r"""
38
+ TESTS::
39
+
40
+ sage: from sage.features.gap import GapPackage
41
+ sage: isinstance(GapPackage("grape", spkg='gap_packages'), GapPackage)
42
+ True
43
+ """
44
+ Feature.__init__(self, f"gap_package_{package}", **kwds)
45
+ self.package = package
46
+
47
+ def _is_present(self):
48
+ r"""
49
+ Return whether or not the GAP package is present.
50
+
51
+ If the package is installed but not yet loaded, it is loaded
52
+ first. This does *not* check that the package is functional.
53
+
54
+ EXAMPLES::
55
+
56
+ sage: from sage.features.gap import GapPackage
57
+ sage: GapPackage("grape", spkg='gap_packages')._is_present() # optional - gap_package_grape
58
+ FeatureTestResult('gap_package_grape', True)
59
+ """
60
+ try:
61
+ from sage.libs.gap.libgap import libgap
62
+ except ImportError:
63
+ return FeatureTestResult(self, False,
64
+ reason="sage.libs.gap is not available")
65
+
66
+ # This returns "true" even if the package is already loaded.
67
+ command = 'LoadPackage("{package}")'.format(package=self.package)
68
+ presence = libgap.eval(command)
69
+
70
+ if presence:
71
+ return FeatureTestResult(self, True,
72
+ reason="`{command}` evaluated to `{presence}` in GAP.".format(command=command, presence=presence))
73
+ else:
74
+ return FeatureTestResult(self, False,
75
+ reason="`{command}` evaluated to `{presence}` in GAP.".format(command=command, presence=presence))
76
+
77
+
78
+ def all_features():
79
+ return [GapPackage("atlasrep", spkg='gap_packages'),
80
+ GapPackage("design", spkg='gap_packages'),
81
+ GapPackage("grape", spkg='gap_packages'),
82
+ GapPackage("guava", spkg='gap_packages'),
83
+ GapPackage("hap", spkg='gap_packages'),
84
+ GapPackage("polycyclic", spkg='gap_packages'),
85
+ GapPackage("qpa", spkg='gap_packages'),
86
+ GapPackage("quagroup", spkg='gap_packages')]
sage/features/gfan.py ADDED
@@ -0,0 +1,38 @@
1
+ # sage_setup: distribution = sagemath-environment
2
+ r"""
3
+ Features for testing the presence of ``gfan``
4
+ """
5
+
6
+ # *****************************************************************************
7
+ # Copyright (C) 2022 Matthias Koeppe
8
+ #
9
+ # Distributed under the terms of the GNU General Public License (GPL)
10
+ # as published by the Free Software Foundation; either version 2 of
11
+ # the License, or (at your option) any later version.
12
+ # https://www.gnu.org/licenses/
13
+ # *****************************************************************************
14
+
15
+ from . import Executable
16
+
17
+
18
+ class GfanExecutable(Executable):
19
+ r"""
20
+ A :class:`~sage.features.Feature` for the :ref:`gfan <spkg_gfan>` executables.
21
+ """
22
+ def __init__(self, cmd=None):
23
+ r"""
24
+ TESTS::
25
+
26
+ sage: from sage.features.gfan import GfanExecutable
27
+ sage: isinstance(GfanExecutable('groebnercone'), GfanExecutable)
28
+ True
29
+ """
30
+ if cmd is None:
31
+ name = "gfan"
32
+ else:
33
+ name = f"gfan_{cmd}"
34
+ Executable.__init__(self, name, executable=name, spkg='gfan', type='standard')
35
+
36
+
37
+ def all_features():
38
+ return [GfanExecutable()]
sage/features/giac.py ADDED
@@ -0,0 +1,30 @@
1
+ # sage_setup: distribution = sagemath-environment
2
+ r"""
3
+ Feature for testing the presence of ``giac``
4
+ """
5
+
6
+ from . import Executable, FeatureTestResult
7
+
8
+ class Giac(Executable):
9
+ r"""
10
+ A :class:`~sage.features.Feature` describing the presence of :ref:`giac <spkg_giac>`.
11
+
12
+ EXAMPLES::
13
+
14
+ sage: from sage.features.giac import Giac
15
+ sage: Giac().is_present() # needs giac
16
+ FeatureTestResult('giac', True)
17
+ """
18
+ def __init__(self):
19
+ r"""
20
+ TESTS::
21
+
22
+ sage: from sage.features.giac import Giac
23
+ sage: isinstance(Giac(), Giac)
24
+ True
25
+ """
26
+ Executable.__init__(self, 'giac', executable='giac',
27
+ spkg='giac', type='standard')
28
+
29
+ def all_features():
30
+ return [Giac()]
@@ -0,0 +1,171 @@
1
+ # sage_setup: distribution = sagemath-environment
2
+ r"""
3
+ Features for testing the presence of graph generator programs ``benzene``, ``buckygen``, ``plantri``
4
+ """
5
+
6
+ # *****************************************************************************
7
+ # Copyright (C) 2016 Julian Rüth
8
+ # 2018 Jeroen Demeyer
9
+ # 2019 Frédéric Chapoton
10
+ # 2021 Matthias Koeppe
11
+ # 2021 Kwankyu Lee
12
+ #
13
+ # Distributed under the terms of the GNU General Public License (GPL)
14
+ # as published by the Free Software Foundation; either version 2 of
15
+ # the License, or (at your option) any later version.
16
+ # https://www.gnu.org/licenses/
17
+ # *****************************************************************************
18
+
19
+ import os
20
+ import subprocess
21
+
22
+ from . import Executable, FeatureTestResult
23
+
24
+
25
+ class Plantri(Executable):
26
+ r"""
27
+ A :class:`~sage.features.Feature` which checks for the :ref:`plantri <spkg_plantri>` binary.
28
+
29
+ EXAMPLES::
30
+
31
+ sage: from sage.features.graph_generators import Plantri
32
+ sage: Plantri().is_present() # optional - plantri
33
+ FeatureTestResult('plantri', True)
34
+ """
35
+ def __init__(self):
36
+ r"""
37
+ TESTS::
38
+
39
+ sage: from sage.features.graph_generators import Plantri
40
+ sage: isinstance(Plantri(), Plantri)
41
+ True
42
+ """
43
+ Executable.__init__(self, name='plantri', spkg='plantri',
44
+ executable='plantri',
45
+ url='http://users.cecs.anu.edu.au/~bdm/plantri/')
46
+
47
+ def is_functional(self):
48
+ r"""
49
+ Check whether ``plantri`` works on trivial input.
50
+
51
+ EXAMPLES::
52
+
53
+ sage: from sage.features.graph_generators import Plantri
54
+ sage: Plantri().is_functional() # optional - plantri
55
+ FeatureTestResult('plantri', True)
56
+ """
57
+ command = ["plantri", "4"]
58
+ try:
59
+ lines = subprocess.check_output(command, stderr=subprocess.STDOUT)
60
+ except subprocess.CalledProcessError as e:
61
+ return FeatureTestResult(self, False,
62
+ reason="Call `{command}` failed with exit code {e.returncode}".format(command=" ".join(command), e=e))
63
+
64
+ expected = b"1 triangulations written"
65
+ if lines.find(expected) == -1:
66
+ return FeatureTestResult(self, False,
67
+ reason="Call `{command}` did not produce output which contains `{expected}`".format(command=" ".join(command), expected=expected))
68
+
69
+ return FeatureTestResult(self, True)
70
+
71
+
72
+ class Buckygen(Executable):
73
+ r"""
74
+ A :class:`~sage.features.Feature` which checks for the :ref:`buckygen <spkg_buckygen>` binary.
75
+
76
+ EXAMPLES::
77
+
78
+ sage: from sage.features.graph_generators import Buckygen
79
+ sage: Buckygen().is_present() # optional - buckygen
80
+ FeatureTestResult('buckygen', True)
81
+ """
82
+ def __init__(self):
83
+ r"""
84
+ TESTS::
85
+
86
+ sage: from sage.features.graph_generators import Buckygen
87
+ sage: isinstance(Buckygen(), Buckygen)
88
+ True
89
+ """
90
+ Executable.__init__(self, name='buckygen', spkg='buckygen',
91
+ executable='buckygen',
92
+ url='http://caagt.ugent.be/buckygen/')
93
+
94
+ def is_functional(self):
95
+ r"""
96
+ Check whether ``buckygen`` works on trivial input.
97
+
98
+ EXAMPLES::
99
+
100
+ sage: from sage.features.graph_generators import Buckygen
101
+ sage: Buckygen().is_functional() # optional - buckygen
102
+ FeatureTestResult('buckygen', True)
103
+ """
104
+ command = ["buckygen", "-d", "22d"]
105
+ try:
106
+ lines = subprocess.check_output(command, stderr=subprocess.STDOUT)
107
+ except subprocess.CalledProcessError as e:
108
+ return FeatureTestResult(self, False,
109
+ reason="Call `{command}` failed with exit code {e.returncode}".format(command=" ".join(command), e=e))
110
+
111
+ expected = b"Number of fullerenes generated with 13 vertices: 0"
112
+ if lines.find(expected) == -1:
113
+ return FeatureTestResult(self, False,
114
+ reason="Call `{command}` did not produce output which contains `{expected}`".format(command=" ".join(command), expected=expected))
115
+
116
+ return FeatureTestResult(self, True)
117
+
118
+
119
+ class Benzene(Executable):
120
+ r"""
121
+ A :class:`~sage.features.Feature` which checks for the :ref:`benzene <spkg_benzene>`
122
+ binary.
123
+
124
+ EXAMPLES::
125
+
126
+ sage: from sage.features.graph_generators import Benzene
127
+ sage: Benzene().is_present() # optional - benzene
128
+ FeatureTestResult('benzene', True)
129
+ """
130
+ def __init__(self):
131
+ r"""
132
+ TESTS::
133
+
134
+ sage: from sage.features.graph_generators import Benzene
135
+ sage: isinstance(Benzene(), Benzene)
136
+ True
137
+ """
138
+ Executable.__init__(self, name='benzene', spkg='benzene',
139
+ executable='benzene',
140
+ url='http://www.grinvin.org/')
141
+
142
+ def is_functional(self):
143
+ r"""
144
+ Check whether ``benzene`` works on trivial input.
145
+
146
+ EXAMPLES::
147
+
148
+ sage: from sage.features.graph_generators import Benzene
149
+ sage: Benzene().is_functional() # optional - benzene
150
+ FeatureTestResult('benzene', True)
151
+ """
152
+ devnull = open(os.devnull, 'wb')
153
+ command = ["benzene", "2", "p"]
154
+ try:
155
+ lines = subprocess.check_output(command, stderr=devnull)
156
+ except subprocess.CalledProcessError as e:
157
+ return FeatureTestResult(self, False,
158
+ reason="Call `{command}` failed with exit code {e.returncode}".format(command=" ".join(command), e=e))
159
+
160
+ expected = b">>planar_code<<"
161
+ if not lines.startswith(expected):
162
+ return FeatureTestResult(self, False,
163
+ reason="Call `{command}` did not produce output that started with `{expected}`.".format(command=" ".join(command), expected=expected))
164
+
165
+ return FeatureTestResult(self, True)
166
+
167
+
168
+ def all_features():
169
+ return [Plantri(),
170
+ Buckygen(),
171
+ Benzene()]
@@ -0,0 +1,117 @@
1
+ # sage_setup: distribution = sagemath-environment
2
+ r"""
3
+ Features for testing the presence of ``graphviz``
4
+ """
5
+
6
+ # ****************************************************************************
7
+ # Copyright (C) 2018 Sebastien Labbe <slabqc@gmail.com>
8
+ # 2021 Matthias Koeppe
9
+ #
10
+ # This program is free software: you can redistribute it and/or modify
11
+ # it under the terms of the GNU General Public License as published by
12
+ # the Free Software Foundation, either version 2 of the License, or
13
+ # (at your option) any later version.
14
+ # https://www.gnu.org/licenses/
15
+ # ****************************************************************************
16
+
17
+ from . import Executable
18
+ from .join_feature import JoinFeature
19
+
20
+
21
+ class dot(Executable):
22
+ r"""
23
+ A :class:`~sage.features.Feature` describing the presence of ``dot``.
24
+
25
+ TESTS::
26
+
27
+ sage: from sage.features.graphviz import dot
28
+ sage: dot().is_present() # optional - graphviz
29
+ FeatureTestResult('dot', True)
30
+ """
31
+ def __init__(self):
32
+ r"""
33
+ TESTS::
34
+
35
+ sage: from sage.features.graphviz import dot
36
+ sage: isinstance(dot(), dot)
37
+ True
38
+ """
39
+ Executable.__init__(self, 'dot', executable='dot',
40
+ spkg='graphviz',
41
+ url='https://www.graphviz.org/')
42
+
43
+
44
+ class neato(Executable):
45
+ r"""
46
+ A :class:`~sage.features.Feature` describing the presence of ``neato``.
47
+
48
+ TESTS:
49
+
50
+ sage: from sage.features.graphviz import neato
51
+ sage: neato().is_present() # optional - graphviz
52
+ FeatureTestResult('neato', True)
53
+ """
54
+ def __init__(self):
55
+ r"""
56
+ TESTS::
57
+
58
+ sage: from sage.features.graphviz import neato
59
+ sage: isinstance(neato(), neato)
60
+ True
61
+ """
62
+ Executable.__init__(self, 'neato', executable='neato',
63
+ spkg='graphviz',
64
+ url='https://www.graphviz.org/')
65
+
66
+
67
+ class twopi(Executable):
68
+ r"""
69
+ A :class:`~sage.features.Feature` describing the presence of ``twopi``.
70
+
71
+ TESTS::
72
+
73
+ sage: from sage.features.graphviz import twopi
74
+ sage: twopi().is_present() # optional - graphviz
75
+ FeatureTestResult('twopi', True)
76
+ """
77
+ def __init__(self):
78
+ r"""
79
+ TESTS::
80
+
81
+ sage: from sage.features.graphviz import twopi
82
+ sage: isinstance(twopi(), twopi)
83
+ True
84
+ """
85
+ Executable.__init__(self, 'twopi', executable='twopi',
86
+ spkg='graphviz',
87
+ url='https://www.graphviz.org/')
88
+
89
+
90
+ class Graphviz(JoinFeature):
91
+ r"""
92
+ A :class:`~sage.features.Feature` describing the presence of
93
+ the :class:`dot`, :class:`neato`, and :class:`twopi` executables from the
94
+ :ref:`graphviz <spkg_graphviz>` package.
95
+
96
+ EXAMPLES::
97
+
98
+ sage: from sage.features.graphviz import Graphviz
99
+ sage: Graphviz().is_present() # optional - graphviz
100
+ FeatureTestResult('graphviz', True)
101
+ """
102
+ def __init__(self):
103
+ r"""
104
+ TESTS::
105
+
106
+ sage: from sage.features.graphviz import Graphviz
107
+ sage: isinstance(Graphviz(), Graphviz)
108
+ True
109
+ """
110
+ JoinFeature.__init__(self, 'graphviz',
111
+ [dot(), neato(), twopi()],
112
+ spkg='graphviz',
113
+ url='https://www.graphviz.org/')
114
+
115
+
116
+ def all_features():
117
+ return [Graphviz()]
@@ -0,0 +1,44 @@
1
+ # sage_setup: distribution = sagemath-environment
2
+ r"""
3
+ Check for igraph
4
+ """
5
+
6
+ # ****************************************************************************
7
+ # Copyright (C) 2021 Matthias Koeppe
8
+ #
9
+ # This program is free software: you can redistribute it and/or modify
10
+ # it under the terms of the GNU General Public License as published by
11
+ # the Free Software Foundation, either version 2 of the License, or
12
+ # (at your option) any later version.
13
+ # https://www.gnu.org/licenses/
14
+ # ****************************************************************************
15
+
16
+ from . import PythonModule
17
+ from .join_feature import JoinFeature
18
+
19
+
20
+ class python_igraph(JoinFeature):
21
+ r"""
22
+ A :class:`sage.features.Feature` describing the presence of the
23
+ Python package :ref:`igraph <spkg_python_igraph>`.
24
+
25
+ EXAMPLES::
26
+
27
+ sage: from sage.features.igraph import python_igraph
28
+ sage: python_igraph().is_present() # optional - python_igraph
29
+ FeatureTestResult('python_igraph', True)
30
+ """
31
+ def __init__(self):
32
+ r"""
33
+ TESTS::
34
+
35
+ sage: from sage.features.igraph import python_igraph
36
+ sage: isinstance(python_igraph(), python_igraph)
37
+ True
38
+ """
39
+ JoinFeature.__init__(self, 'python_igraph',
40
+ [PythonModule('igraph', spkg='python_igraph',
41
+ url='http://igraph.org')])
42
+
43
+ def all_features():
44
+ return [python_igraph()]
@@ -0,0 +1,138 @@
1
+ # sage_setup: distribution = sagemath-environment
2
+ r"""
3
+ Feature for testing the presence of ``imagemagick``
4
+
5
+ Currently we only check for the presence of ``convert`` or ``magick``. When needed, other
6
+ commands like ``magick-script``, ``mogrify``,
7
+ ``identify``, ``composite``, ``montage``, ``compare``, etc. could be also
8
+ checked in this module.
9
+ """
10
+
11
+ # ****************************************************************************
12
+ # Copyright (C) 2018-2022 Sebastien Labbe <slabqc@gmail.com>
13
+ #
14
+ # This program is free software: you can redistribute it and/or modify
15
+ # it under the terms of the GNU General Public License as published by
16
+ # the Free Software Foundation, either version 2 of the License, or
17
+ # (at your option) any later version.
18
+ # https://www.gnu.org/licenses/
19
+ # ****************************************************************************
20
+
21
+ from . import Executable, FeatureTestResult
22
+ from .join_feature import JoinFeature
23
+
24
+ class Magick(Executable):
25
+ r"""
26
+ A :class:`~sage.features.Feature` describing the presence of ``magick`` or the deprecated ``convert``.
27
+
28
+ EXAMPLES::
29
+
30
+ sage: from sage.features.imagemagick import Magick
31
+ sage: Magick().is_present() # optional - imagemagick
32
+ FeatureTestResult('magick', True)
33
+ """
34
+ def __init__(self):
35
+ r"""
36
+ TESTS::
37
+
38
+ sage: from sage.features.imagemagick import Magick
39
+ sage: isinstance(Magick(), Magick)
40
+ True
41
+ """
42
+ Executable.__init__(self, 'magick', executable='magick')
43
+ try:
44
+ _ = self.absolute_filename()
45
+ except RuntimeError:
46
+ Executable.__init__(self, 'magick', executable='convert')
47
+
48
+ def is_functional(self):
49
+ r"""
50
+ Return whether command ``magick`` or ``convert`` in the path is functional.
51
+
52
+ EXAMPLES::
53
+
54
+ sage: from sage.features.imagemagick import Magick
55
+ sage: Magick().is_functional() # optional - imagemagick
56
+ FeatureTestResult('magick', True)
57
+ """
58
+ # Create the content of 1-pixel png file
59
+ content = b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x00\x00\x00\x00:~\x9bU\x00\x00\x00\nIDATx\x9cc`\x00\x00\x00\x02\x00\x01H\xaf\xa4q\x00\x00\x00\x00IEND\xaeB`\x82'
60
+
61
+ # NOTE:
62
+ #
63
+ # This is how the above content of a 1 pixel PNG was created::
64
+ #
65
+ # sage: import numpy as np
66
+ # sage: from PIL import Image
67
+ # sage: image = Image.fromarray(np.array([[100]], dtype=np.uint8))
68
+ # sage: image.save('file.png')
69
+ # sage: with open('file.png', 'rb') as f:
70
+ # ....: content = f.read()
71
+
72
+ # create a png file with the content
73
+ from sage.misc.temporary_file import tmp_filename
74
+ base_filename_png = tmp_filename(ext='.png')
75
+ with open(base_filename_png, 'wb') as f:
76
+ f.write(content)
77
+
78
+ # Set up filenames
79
+ import os
80
+ base, filename_png = os.path.split(base_filename_png)
81
+ filename, _png = os.path.splitext(filename_png)
82
+ filename_gif = filename + '.gif'
83
+
84
+ # running command magick/convert (taken from sage/plot/animate.py)
85
+ from subprocess import run
86
+ cmd = [self.executable, '-dispose', 'Background', '-delay', '20',
87
+ '-loop', '0', filename_png, filename_gif]
88
+
89
+ try:
90
+ result = run(cmd, cwd=base, capture_output=True, text=True)
91
+ except OSError as e:
92
+ return FeatureTestResult(self, False, reason='Running command "{}" '
93
+ 'raised an OSError "{}" '.format(' '.join(cmd), e))
94
+
95
+ # If an error occurred, return False
96
+ if result.returncode:
97
+ return FeatureTestResult(self, False, reason='Running command "{}" '
98
+ 'returned nonzero exit status "{}" with stderr '
99
+ '"{}" and stdout "{}".'.format(result.args,
100
+ result.returncode,
101
+ result.stderr.strip(),
102
+ result.stdout.strip()))
103
+
104
+ # If necessary, run more tests here
105
+ # ...
106
+
107
+ # The command seems functional
108
+ return FeatureTestResult(self, True)
109
+
110
+
111
+ class ImageMagick(JoinFeature):
112
+ r"""
113
+ A :class:`~sage.features.Feature` describing the presence of
114
+ :ref:`ImageMagick <spkg_imagemagick>`
115
+
116
+ Currently, only the availability of the :class:`magick` (or :class:`convert`) program is checked.
117
+
118
+ EXAMPLES::
119
+
120
+ sage: from sage.features.imagemagick import ImageMagick
121
+ sage: ImageMagick().is_present() # optional - imagemagick
122
+ FeatureTestResult('imagemagick', True)
123
+ """
124
+ def __init__(self):
125
+ r"""
126
+ TESTS::
127
+
128
+ sage: from sage.features.imagemagick import ImageMagick
129
+ sage: isinstance(ImageMagick(), ImageMagick)
130
+ True
131
+ """
132
+ JoinFeature.__init__(self, 'imagemagick',
133
+ [Magick()],
134
+ spkg='imagemagick',
135
+ url='https://www.imagemagick.org/')
136
+
137
+ def all_features():
138
+ return [ImageMagick()]