Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sage
Path: blob/develop/build/sage_bootstrap/creator.py
4052 views
1
# -*- coding: utf-8 -*-
2
"""
3
Package Creator
4
"""
5
6
# ****************************************************************************
7
# Copyright (C) 2015-2016 Volker Braun <[email protected]>
8
# 2020-2024 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
import os
18
19
import logging
20
log = logging.getLogger()
21
22
from sage_bootstrap.env import SAGE_ROOT
23
24
25
class PackageCreator(object):
26
27
def __init__(self, package_name):
28
self.package_name = package_name
29
self.path = os.path.join(SAGE_ROOT, 'build', 'pkgs', package_name)
30
try:
31
os.mkdir(self.path)
32
except OSError:
33
pass
34
35
def set_version(self, version):
36
"""
37
Write the version to ``package-version.txt``
38
"""
39
with open(os.path.join(self.path, 'package-version.txt'), 'w+') as f:
40
f.write(version)
41
f.write('\n')
42
43
def set_type(self, pkg_type):
44
"""
45
Write the package type to ``type``
46
"""
47
with open(os.path.join(self.path, 'type'), 'w+') as f:
48
f.write(pkg_type)
49
f.write('\n')
50
51
def set_tarball(self, tarball, upstream_url):
52
"""
53
Write the tarball name pattern to ``checksums.ini``
54
"""
55
with open(os.path.join(self.path, 'checksums.ini'), 'w+') as f:
56
f.write('tarball={0}'.format(tarball))
57
f.write('\n')
58
if upstream_url:
59
f.write('upstream_url={0}'.format(upstream_url))
60
f.write('\n')
61
62
def set_description(self, description, license, upstream_contact):
63
"""
64
Write the ``SPKG.rst`` file
65
"""
66
with open(os.path.join(self.path, 'SPKG.rst'), 'w+') as f:
67
# Attempt to bring title to a common style
68
if description.startswith(self.package_name + ':'):
69
description = description[len(self.package_name + ':'):]
70
if description.startswith(self.package_name + ' is'):
71
description = description[len(self.package_name + ' is'):]
72
description = description.strip()
73
if not description.endswith('etc.'):
74
description = description.rstrip('.')
75
if description.startswith('A ') or description.startswith('a '):
76
description = description[2:].strip()
77
if description.startswith('An ') or description.startswith('an '):
78
description = description[3:].strip()
79
if description:
80
description = description[0].upper() + description[1:]
81
82
def heading(title, char='-'):
83
return '{0}\n{1}\n\n'.format(title, char * len(title))
84
if description:
85
title = '{0}: {1}'.format(self.package_name, description)
86
else:
87
title = self.package_name
88
f.write(heading(title, '='))
89
f.write(heading('Description'))
90
if description:
91
f.write('{0}\n\n'.format(description))
92
f.write(heading('License'))
93
if license:
94
f.write('{0}\n\n'.format(license))
95
f.write(heading('Upstream Contact'))
96
if upstream_contact:
97
f.write('{0}\n\n'.format(upstream_contact))
98
99
def _remove_files(self, files):
100
"""
101
Remove ``files`` from the package directory if they exist.
102
"""
103
for file in files:
104
try:
105
os.remove(os.path.join(self.path, file))
106
except OSError:
107
pass
108
109
def set_python_data_and_scripts(self, pypi_package_name=None, source='normal', dependencies=None):
110
"""
111
Write the file ``dependencies`` and other files for Python packages.
112
113
If ``source`` is ``"normal"``, write the files ``spkg-install.in`` and
114
``version_requirements.txt``.
115
116
If ``source`` is ``"wheel"``, write the file ``version_requirements.txt``.
117
118
If ``source`` is ``"pip"``, write the file ``requirements.txt``.
119
120
Remove existing files that belong to other source types.
121
"""
122
if pypi_package_name is None:
123
pypi_package_name = self.package_name
124
with open(os.path.join(self.path, 'dependencies'), 'w+') as f:
125
if dependencies:
126
dependencies = ' '.join(dependencies)
127
else:
128
dependencies = ''
129
if source == 'wheel':
130
dependencies_order_only = 'pip $(PYTHON)'
131
else:
132
dependencies_order_only = '$(PYTHON_TOOLCHAIN) $(PYTHON)'
133
f.write(dependencies + ' | ' + dependencies_order_only + '\n\n')
134
f.write('----------\nAll lines of this file are ignored except the first.\n')
135
if source == 'normal':
136
with open(os.path.join(self.path, 'spkg-install.in'), 'w+') as f:
137
f.write('cd src\nsdh_pip_install .\n')
138
with open(os.path.join(self.path, 'version_requirements.txt'), 'w+') as f:
139
f.write('{0}\n'.format(pypi_package_name))
140
# Remove this file, which would mark the package as a pip package.
141
self._remove_files(['requirements.txt'])
142
elif source == 'wheel':
143
with open(os.path.join(self.path, 'version_requirements.txt'), 'w+') as f:
144
f.write('{0}\n'.format(pypi_package_name))
145
# Remove this file, which would mark the package as a pip package.
146
self._remove_files(['requirements.txt'])
147
if pypi_package_name != 'pip':
148
# 'pip' should be the only wheel package that has a custom spkg-install.in script.
149
# Remove the script for all other wheel packages, to avoid errors when
150
# switching from normal to wheel packages.
151
self._remove_files(['spkg-build.in', 'spkg-install.in', 'spkg-install'])
152
elif source == 'pip':
153
with open(os.path.join(self.path, 'requirements.txt'), 'w+') as f:
154
f.write('{0}\n'.format(pypi_package_name))
155
self._remove_files(['checksums.ini', 'spkg-build.in', 'spkg-install.in', 'spkg-install', 'install-requires.txt'])
156
elif source == 'script':
157
self._remove_files(['checksums.ini', 'requirements.txt'])
158
else:
159
raise ValueError('package source must be one of normal, script, pip, or wheel')
160
161