diff options
-rw-r--r-- | CHANGES | 7 | ||||
-rw-r--r-- | README.rst | 11 | ||||
-rw-r--r-- | __init__.py | 6 | ||||
-rw-r--r-- | _doc/_static/pypi.svg | 2 | ||||
-rw-r--r-- | _test/test_issues.py | 26 | ||||
-rw-r--r-- | scanner.py | 1 | ||||
-rw-r--r-- | setup.py | 149 |
7 files changed, 60 insertions, 142 deletions
@@ -1,3 +1,10 @@ +[0, 16, 1]: 2019-08-08 + - Force the use of new version of ruamel.yaml.clib (reported by `Alex Joz + <https://bitbucket.org/%7B9af55900-2534-4212-976c-61339b6ffe14%7D/>`__) + - Allow '#' in tag URI as these are allowed in YAML 1.2 (reported by + `Thomas Smith + <https://bitbucket.org/%7Bd4c57a72-f041-4843-8217-b4d48b6ece2f%7D/>`__) + [0, 16, 0]: 2019-07-25 - split of C source that generates .so file to ruamel.yaml.clib - duplicate keys are now an error when working with the old API as well @@ -4,8 +4,8 @@ ruamel.yaml ``ruamel.yaml`` is a YAML 1.2 loader/dumper package for Python. -:version: 0.16.0 -:updated: 2019-07-25 +:version: 0.16.1 +:updated: 2019-08-08 :documentation: http://yaml.readthedocs.io :repository: https://bitbucket.org/ruamel/yaml :pypi: https://pypi.org/project/ruamel.yaml/ @@ -54,6 +54,13 @@ ChangeLog .. should insert NEXT: at the beginning of line for next key (with empty line) +0.16.1 (2019-08-08): + - Force the use of new version of ruamel.yaml.clib (reported by `Alex Joz + <https://bitbucket.org/%7B9af55900-2534-4212-976c-61339b6ffe14%7D/>`__) + - Allow '#' in tag URI as these are allowed in YAML 1.2 (reported by + `Thomas Smith + <https://bitbucket.org/%7Bd4c57a72-f041-4843-8217-b4d48b6ece2f%7D/>`__) + 0.16.0 (2019-07-25): - split of C source that generates .so file to ruamel.yaml.clib - duplicate keys are now an error when working with the old API as well diff --git a/__init__.py b/__init__.py index 33e1d63..995bca9 100644 --- a/__init__.py +++ b/__init__.py @@ -7,8 +7,8 @@ if False: # MYPY _package_data = dict( full_package_name='ruamel.yaml', - version_info=(0, 16, 0), - __version__='0.16.0', + version_info=(0, 16, 1), + __version__='0.16.1', author='Anthon van der Neut', author_email='a.van.der.neut@ruamel.eu', description='ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order', # NOQA @@ -17,7 +17,7 @@ _package_data = dict( extras_require={':platform_python_implementation=="CPython" and python_version<="2.7"': [ 'ruamel.ordereddict', ], ':platform_python_implementation=="CPython" and python_version<"3.8"': [ - 'ruamel.yaml.clib', + 'ruamel.yaml.clib>=0.1.2', ], 'jinja2': ['ruamel.yaml.jinja2>=0.2'], 'docs': ['ryd']}, # NOQA # test='#include "ext/yaml.h"\n\nint main(int argc, char* argv[])\n{\nyaml_parser_t parser;\nparser = parser; /* prevent warning */\nreturn 0;\n}\n', # NOQA diff --git a/_doc/_static/pypi.svg b/_doc/_static/pypi.svg index 025942d..aa448d9 100644 --- a/_doc/_static/pypi.svg +++ b/_doc/_static/pypi.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="86" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h33v20H0z"/><path fill="#007ec6" d="M33 0h53v20H33z"/><path fill="url(#b)" d="M0 0h86v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"> <text x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="230">pypi</text><text x="175" y="140" transform="scale(.1)" textLength="230">pypi</text><text x="585" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">0.16.0</text><text x="585" y="140" transform="scale(.1)" textLength="430">0.16.0</text></g> </svg> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="86" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h33v20H0z"/><path fill="#007ec6" d="M33 0h53v20H33z"/><path fill="url(#b)" d="M0 0h86v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"> <text x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="230">pypi</text><text x="175" y="140" transform="scale(.1)" textLength="230">pypi</text><text x="585" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">0.16.1</text><text x="585" y="140" transform="scale(.1)" textLength="430">0.16.1</text></g> </svg> diff --git a/_test/test_issues.py b/_test/test_issues.py index 90128dd..3692f61 100644 --- a/_test/test_issues.py +++ b/_test/test_issues.py @@ -824,6 +824,32 @@ class TestIssues: dc = copy.deepcopy(data) assert round_trip_dump(dc) == inp + def test_issue_300(self): + from ruamel.yaml import YAML + + inp = dedent(""" + %YAML 1.2 + %TAG ! tag:example.com,2019/path#fragment + --- + null + """) + YAML().load(inp) + + def test_issue_300a(self): + import ruamel.yaml + + inp = dedent(""" + %YAML 1.1 + %TAG ! tag:example.com,2019/path#fragment + --- + null + """) + yaml = YAML() + yaml.version = (1, 1) # This should not be necessary -> issue 301 + with pytest.raises(ruamel.yaml.scanner.ScannerError, + match='while scanning a directive'): + yaml.load(inp) + # @pytest.mark.xfail(strict=True, reason='bla bla', raises=AssertionError) # def test_issue_ xxx(self): # inp = """ @@ -1675,6 +1675,7 @@ class Scanner(object): or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' or ch in "-;/?:@&=+$,_.!~*'()[]%" + or ((self.scanner_processing_version > (1, 1)) and ch == "#") ): if ch == '%': chunks.append(self.reader.prefix(length)) @@ -1,5 +1,6 @@ # # header # coding: utf-8 +# dd: 20190807 from __future__ import print_function, absolute_import, division, unicode_literals @@ -19,6 +20,8 @@ from setuptools import setup, Extension, Distribution # NOQA from setuptools.command import install_lib # NOQA from setuptools.command.sdist import sdist as _sdist # NOQA +from setuptools.namespaces import Installer as NameSpaceInstaller # NOQA + if __name__ != '__main__': raise NotImplementedError('should never include setup.py') @@ -306,100 +309,6 @@ except ImportError: _bdist_wheel_available = False -class InMemoryZipFile(object): - def __init__(self, file_name=None): - try: - from cStringIO import StringIO - except ImportError: - from io import BytesIO as StringIO - import zipfile - - self.zip_file = zipfile - # Create the in-memory file-like object - self._file_name = file_name - self._removed_names = [] - self.in_memory_data = StringIO() - # Create the in-memory zipfile - self.in_memory_zip = self.zip_file.ZipFile( - self.in_memory_data, 'w', self.zip_file.ZIP_DEFLATED, False - ) - self.in_memory_zip.debug = 3 - - def append(self, filename_in_zip, file_contents): - """Appends a file with name filename_in_zip and contents of - file_contents to the in-memory zip. - """ - if filename_in_zip.endswith('.dist-info/RECORD') and self._removed_names: - # this is normally the last file - # remove any names filtered, to placate auditwheel - convert = not isinstance(file_contents, string_type) - if convert: - file_contents = file_contents.decode('utf-8') - outlines = [] - for line in file_contents.splitlines(True): - for fn in self._removed_names: - fn = fn + ',' # comma is the record seperator in RECORD - if line.startswith(fn): - break - else: - outlines.append(line) - file_contents = ''.join(outlines) - self.in_memory_zip.writestr(filename_in_zip, file_contents) - return self # so you can daisy-chain - - def write_to_file(self, filename): - """Writes the in-memory zip to a file.""" - # Mark the files as having been created on Windows so that - # Unix permissions are not inferred as 0000 - for zfile in self.in_memory_zip.filelist: - zfile.create_system = 0 - self.in_memory_zip.close() - with open(filename, 'wb') as f: - f.write(self.in_memory_data.getvalue()) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - if self._file_name is None: - return - self.write_to_file(self._file_name) - - def delete_from_zip_file(self, pattern=None, file_names=None): - """ - zip_file can be a string or a zipfile.ZipFile object, the latter will be closed - any name in file_names is deleted from the list of files to write to the new zip - (using .append) - all file_names provided have to be in the ZIP archive or else an IOError is raised - """ - if pattern and isinstance(pattern, string_type): - import re - - pattern = re.compile(pattern) - if file_names: - if not isinstance(file_names, list): - file_names = [file_names] - else: - file_names = [] - with self.zip_file.ZipFile(self._file_name) as zf: - for l in zf.infolist(): - if l.filename in file_names: - file_names.remove(l.filename) - self._removed_names.append(l.filename) - continue - if pattern and pattern.match(l.filename): - self._removed_names.append(l.filename) - continue - self.append(l.filename, zf.read(l)) - if file_names: - raise IOError( - '[Errno 2] No such file{}: {}'.format( - "" if len(file_names) == 1 else 's', - ', '.join([repr(f) for f in file_names]), - ) - ) - - class NameSpacePackager(object): def __init__(self, pkg_data): assert isinstance(pkg_data, dict) @@ -408,6 +317,8 @@ class NameSpacePackager(object): self._split = None self.depth = self.full_package_name.count('.') self.nested = self._pkg_data.get('nested', False) + if self.nested: + NameSpaceInstaller.install_namespaces = lambda x: None self.command = None self.python_version() self._pkg = [None, None] # required and pre-installable packages @@ -769,14 +680,14 @@ class NameSpacePackager(object): ep = self._pkg_data.get('extras_require') return ep - @property - def data_files(self): - df = self._pkg_data.get('data_files', []) - if self.has_mit_lic(): - df.append('LICENSE') - if not df: - return None - return [('.', df)] + # @property + # def data_files(self): + # df = self._pkg_data.get('data_files', []) + # if self.has_mit_lic(): + # df.append('LICENSE') + # if not df: + # return None + # return [('.', df)] @property def package_data(self): @@ -1018,30 +929,6 @@ def main(): pass if nsp.wheel(kw, setup): - if nsp.nested and 'bdist_wheel' in sys.argv: - try: - d = sys.argv[sys.argv.index('-d') + 1] - except ValueError: - dist_base = os.environ.get('PYDISTBASE') - if dist_base: - d = os.path.join(dist_base, nsp.full_package_name) - else: - d = 'dist' - dashed_vs = '-' + version_str + '-' - latest_mtime = -1 - full_name = None - for x in os.listdir(d): - if x.endswith('.whl') and dashed_vs in x: - # remove .pth file from the wheel - fn = os.path.join(d, x) - if os.path.getmtime(fn) > latest_mtime: - full_name = fn - if full_name is None: - print('no wheel file found in', d) - else: - print('patching .pth from {}'.format(full_name)) - with InMemoryZipFile(full_name) as imz: - imz.delete_from_zip_file(nsp.full_package_name + '.*.pth') return for x in ['-c', 'egg_info', '--egg-base', 'pip-egg-info']: if x not in sys.argv: @@ -1066,16 +953,6 @@ def main(): break try_dir = os.path.dirname(try_dir) setup(**kw) - if nsp.nested and sys.argv[:2] == ['-c', 'bdist_wheel']: - d = sys.argv[sys.argv.index('-d') + 1] - for x in os.listdir(d): - if x.endswith('.whl'): - # remove .pth file from the wheel - full_name = os.path.join(d, x) - print('patching .pth from', full_name) - with InMemoryZipFile(full_name) as imz: - imz.delete_from_zip_file(nsp.full_package_name + '.*.pth') - break main() |