4 DESCRIPTION
= "YAML parser and emitter for Python"
5 LONG_DESCRIPTION
= """\
6 YAML is a data serialization format designed for human readability
7 and interaction with scripting languages. PyYAML is a YAML parser
8 and emitter for Python.
10 PyYAML features a complete YAML 1.1 parser, Unicode support, pickle
11 support, capable extension API, and sensible error messages. PyYAML
12 supports standard YAML tags and provides Python-specific tags that
13 allow to represent an arbitrary Python object.
15 PyYAML is applicable for a broad range of tasks from complex
16 configuration files to object serialization and persistence."""
17 AUTHOR
= "Kirill Simonov"
18 AUTHOR_EMAIL
= 'xi@resolvent.net'
21 URL
= "https://pyyaml.org/"
22 DOWNLOAD_URL
= "https://pypi.org/project/PyYAML/"
24 "Development Status :: 5 - Production/Stable",
25 "Intended Audience :: Developers",
26 "License :: OSI Approved :: MIT License",
27 "Operating System :: OS Independent",
28 "Programming Language :: Cython",
29 "Programming Language :: Python",
30 "Programming Language :: Python :: 3",
31 "Programming Language :: Python :: 3.6",
32 "Programming Language :: Python :: 3.7",
33 "Programming Language :: Python :: 3.8",
34 "Programming Language :: Python :: 3.9",
35 "Programming Language :: Python :: 3.10",
36 "Programming Language :: Python :: 3.11",
37 "Programming Language :: Python :: Implementation :: CPython",
38 "Programming Language :: Python :: Implementation :: PyPy",
39 "Topic :: Software Development :: Libraries :: Python Modules",
40 "Topic :: Text Processing :: Markup",
43 'Bug Tracker': 'https://github.com/yaml/pyyaml/issues',
44 'CI': 'https://github.com/yaml/pyyaml/actions',
45 'Documentation': 'https://pyyaml.org/wiki/PyYAMLDocumentation',
46 'Mailing lists': 'http://lists.sourceforge.net/lists/listinfo/yaml-core',
47 'Source Code': 'https://github.com/yaml/pyyaml',
55 yaml_emitter_t emitter;
57 yaml_parser_initialize(&parser);
58 yaml_parser_delete(&parser);
60 yaml_emitter_initialize(&emitter);
61 yaml_emitter_delete(&emitter);
68 import sys
, os
, os
.path
, pathlib
, platform
, shutil
, tempfile
, warnings
70 # for newer setuptools, enable the embedded distutils before importing setuptools/distutils to avoid warnings
71 os
.environ
['SETUPTOOLS_USE_DISTUTILS'] = 'local'
73 from setuptools
import setup
, Command
, Distribution
as _Distribution
, Extension
as _Extension
74 from setuptools
.command
.build_ext
import build_ext
as _build_ext
75 # NB: distutils imports must remain below setuptools to ensure we use the embedded version
76 from distutils
import log
77 from distutils
.errors
import DistutilsError
, CompileError
, LinkError
, DistutilsPlatformError
80 if 'sdist' in sys
.argv
or os
.environ
.get('PYYAML_FORCE_CYTHON') == '1':
84 from Cython
.Distutils
.extension
import Extension
as _Extension
85 from Cython
.Distutils
import build_ext
as _build_ext
92 from wheel
.bdist_wheel
import bdist_wheel
97 # on Windows, disable wheel generation warning noise
98 windows_ignore_warnings
= [
99 "Unknown distribution option: 'python_requires'",
100 "Config variable 'Py_DEBUG' is unset",
101 "Config variable 'WITH_PYMALLOC' is unset",
102 "Config variable 'Py_UNICODE_SIZE' is unset",
103 "Cython directive 'language_level' not set"
106 if platform
.system() == 'Windows':
107 for w
in windows_ignore_warnings
:
108 warnings
.filterwarnings('ignore', w
)
111 class Distribution(_Distribution
):
112 def __init__(self
, attrs
=None):
113 _Distribution
.__init
__(self
, attrs
)
114 if not self
.ext_modules
:
116 for idx
in range(len(self
.ext_modules
)-1, -1, -1):
117 ext
= self
.ext_modules
[idx
]
118 if not isinstance(ext
, Extension
):
120 setattr(self
, ext
.attr_name
, None)
121 self
.global_options
= [
122 (ext
.option_name
, None,
123 "include %s (default if %s is available)"
124 % (ext
.feature_description
, ext
.feature_name
)),
125 (ext
.neg_option_name
, None,
126 "exclude %s" % ext
.feature_description
),
127 ] + self
.global_options
128 self
.negative_opt
= self
.negative_opt
.copy()
129 self
.negative_opt
[ext
.neg_option_name
] = ext
.option_name
131 def has_ext_modules(self
):
132 if not self
.ext_modules
:
134 for ext
in self
.ext_modules
:
135 with_ext
= self
.ext_status(ext
)
136 if with_ext
is None or with_ext
:
140 def ext_status(self
, ext
):
141 implementation
= platform
.python_implementation()
142 if implementation
not in ['CPython', 'PyPy']:
144 if isinstance(ext
, Extension
):
145 # the "build by default" behavior is implemented by this returning None
146 with_ext
= getattr(self
, ext
.attr_name
) or os
.environ
.get('PYYAML_FORCE_{0}'.format(ext
.feature_name
.upper()))
148 with_ext
= int(with_ext
) # attempt coerce envvar to int
156 class Extension(_Extension
):
158 def __init__(self
, name
, sources
, feature_name
, feature_description
,
159 feature_check
, **kwds
):
161 for filename
in sources
[:]:
162 base
, ext
= os
.path
.splitext(filename
)
164 sources
.remove(filename
)
165 sources
.append('%s.c' % base
)
166 _Extension
.__init
__(self
, name
, sources
, **kwds
)
167 self
.feature_name
= feature_name
168 self
.feature_description
= feature_description
169 self
.feature_check
= feature_check
170 self
.attr_name
= 'with_' + feature_name
.replace('-', '_')
171 self
.option_name
= 'with-' + feature_name
172 self
.neg_option_name
= 'without-' + feature_name
175 class build_ext(_build_ext
):
180 for ext
in self
.extensions
:
181 with_ext
= self
.distribution
.ext_status(ext
)
192 except DistutilsPlatformError
:
193 exc
= sys
.exc_info()[1]
196 log
.warn("skipping build_ext")
200 def get_source_files(self
):
201 self
.check_extensions_list(self
.extensions
)
203 for ext
in self
.extensions
:
205 self
.cython_sources(ext
.sources
, ext
)
206 for filename
in ext
.sources
:
207 filenames
.append(filename
)
208 base
= os
.path
.splitext(filename
)[0]
209 for ext
in ['c', 'h', 'pyx', 'pxd']:
210 filename
= '%s.%s' % (base
, ext
)
211 if filename
not in filenames
and os
.path
.isfile(filename
):
212 filenames
.append(filename
)
215 def get_outputs(self
):
216 self
.check_extensions_list(self
.extensions
)
218 for ext
in self
.extensions
:
219 fullname
= self
.get_ext_fullname(ext
.name
)
220 filename
= os
.path
.join(self
.build_lib
,
221 self
.get_ext_filename(fullname
))
222 if os
.path
.isfile(filename
):
223 outputs
.append(filename
)
226 def build_extensions(self
):
227 self
.check_extensions_list(self
.extensions
)
228 for ext
in self
.extensions
:
229 with_ext
= self
.distribution
.ext_status(ext
)
230 if with_ext
is not None and not with_ext
:
233 ext
.sources
= self
.cython_sources(ext
.sources
, ext
)
235 self
.build_extension(ext
)
236 except (CompileError
, LinkError
):
237 if with_ext
is not None:
239 log
.warn("Error compiling module, falling back to pure Python")
246 def initialize_options(self
):
249 def finalize_options(self
):
253 build_cmd
= self
.get_finalized_command('build')
256 # running the tests this way can pollute the post-MANIFEST build sources
257 # (see https://github.com/yaml/pyyaml/issues/527#issuecomment-921058344)
258 # until we remove the test command, run tests from an ephemeral copy of the intermediate build sources
259 tempdir
= tempfile
.TemporaryDirectory(prefix
='test_pyyaml')
262 # have to create a subdir since we don't get dir_exists_ok on copytree until 3.8
263 temp_test_path
= pathlib
.Path(tempdir
.name
) / 'pyyaml'
264 shutil
.copytree(build_cmd
.build_lib
, temp_test_path
)
265 sys
.path
.insert(0, str(temp_test_path
))
266 sys
.path
.insert(0, 'tests/lib')
269 if not test_all
.main([]):
270 raise DistutilsError("Tests failed")
273 # this can fail under Windows; best-effort cleanup
280 'build_ext': build_ext
,
284 cmdclass
['bdist_wheel'] = bdist_wheel
287 if __name__
== '__main__':
292 description
=DESCRIPTION
,
293 long_description
=LONG_DESCRIPTION
,
295 author_email
=AUTHOR_EMAIL
,
299 download_url
=DOWNLOAD_URL
,
300 classifiers
=CLASSIFIERS
,
301 project_urls
=PROJECT_URLS
,
303 package_dir
={'': 'lib'},
304 packages
=['yaml', '_yaml'],
306 Extension('yaml._yaml', ['yaml/_yaml.pyx'],
307 'libyaml', "LibYAML bindings", LIBYAML_CHECK
,
311 distclass
=Distribution
,
313 python_requires
='>=3.6',