The following code was working on 3.13 but no longer works in 5.1:
import yaml
class Ref(yaml.YAMLObject):
yaml_tag = '!Ref'
def __init__(self, val):
self.val = val
@classmethod
def from_yaml(cls, loader, node):
return cls(node.value)
yaml.load('Foo: !Ref bar')
I get the following exception on 5.1:
yaml.constructor.ConstructorError: could not determine a constructor for the tag '!Ref'
in "<unicode string>", line 1, column 6:
Foo: !Ref bar
This is true whether I use yaml.load, yaml.full_load or yaml.unsafe_load.
Try
yaml.load('Foo: !Ref bar', Loader=yaml.Loader)
I'm not sure though if this is intentional.
Will have a closer look later.
It works with Loader=yaml.Loader. Thanks!
ok, I think I see it now. From https://github.com/yaml/pyyaml/blob/e471e86bf6dabdad45a1438c20a4a5c033eb9034/lib/yaml/__init__.py#L386, the loader for metaclass-driven custom tags defaults to yaml.Loader. The following also works for me:
import yaml
class Ref(yaml.YAMLObject):
yaml_loader = yaml.SafeLoader
yaml_tag = '!Ref'
def __init__(self, val):
self.val = val
@classmethod
def from_yaml(cls, loader, node):
return cls(node.value)
yaml.safe_load('Foo: !Ref bar')
safe_load doesn't work for me but Loader=yaml.Loader does.
Today I encountered the same problem. Even the example straight from the documentation on the homepage does not work anymore
#!/usr/bin/env python
import yaml
class Monster(yaml.YAMLObject):
yaml_tag = u'!Monster'
def __init__(self, name, hp, ac, attacks):
self.name = name
self.hp = hp
self.ac = ac
self.attacks = attacks
def __repr__(self):
return "%s(name=%r, hp=%r, ac=%r, attacks=%r)" % (
self.__class__.__name__, self.name, self.hp, self.ac, self.attacks)
yaml.unsafe_load("""
--- !Monster
name: Cave spider
hp: [2,6] # 2d6
ac: 16
attacks: [BITE, HURT]
""")
Backtrace:
Traceback (most recent call last):
File "./testfile", line 21, in <module>
""")
File "/home/user/.local/lib/python2.7/site-packages/yaml/__init__.py", line 182, in unsafe_load
return load(stream, UnsafeLoader)
File "/home/user/.local/lib/python2.7/site-packages/yaml/__init__.py", line 114, in load
return loader.get_single_data()
File "/home/user/.local/lib/python2.7/site-packages/yaml/constructor.py", line 45, in get_single_data
return self.construct_document(node)
File "/home/user/.local/lib/python2.7/site-packages/yaml/constructor.py", line 49, in construct_document
data = self.construct_object(node)
File "/home/user/.local/lib/python2.7/site-packages/yaml/constructor.py", line 94, in construct_object
data = constructor(self, node)
File "/home/user/.local/lib/python2.7/site-packages/yaml/constructor.py", line 420, in construct_undefined
node.start_mark)
yaml.constructor.ConstructorError: could not determine a constructor for the tag '!Monster'
in "<string>", line 2, column 5:
--- !Monster
^
Edit:
This seems to work (why?)
yaml.load(..., Loader=yaml.Loader)
Yeah, the problem is that the default loader for load is now FullLoader, but the YAMLObject still uses yaml.Loader. #271 is similar.
We are discussing what to do.
I created #273
@kgutwin, i am facing same issue:
Python 2.7
Pyyaml: 5.1
Error: yaml.constructor.ConstructorError: could not determine a constructor for the tag 'tag:yaml.org,2002:python/name:pymdownx.emoji.to_svg'
new_file.yml
extensions:
- pymdownx.emoji:
emoji_generator: !regexp:pymdownx.emoji.to_svg
parse.py
import re
yaml.SafeLoader.add_constructor(u'!regexp', lambda l, n: re.compile(l.construct_scalar(n)))
with open("new_file.yml", 'r') as stream:
print yaml.load(stream)
This is a breaking change, and is likely to break a ton of code out there that worked just fine: I spent myself a whole afternoon trying to figure out what I'd changed that broke all my tests.
Are you guys going to revert changes, or provide a better error message (at the very least)?
yaml.load('Foo: !Ref bar', Loader=yaml.Loader) does not work in Python 3.6.8, Pyaml 5.1.1, what is the current workaround?
yaml.load('Foo: !Ref bar', Loader=yaml.Loader)does not work in Python 3.6.8, Pyaml 5.1.1, what is the current workaround?
It worked like a charm for my
(_after a day of trial and researching about the issue_)
it saved my day...
Python 3.6.9
PyYAML==5.1.2
We just released 5.2b1 https://pypi.org/project/PyYAML/5.2b1/ which should fix this.
None of the workarounds above worked for me, I had to use this loader:
Loader=yaml.BaseLoader
on
Python 3.7.0
PyYaml==5.1.2 or == 5.2b1
_(edited)_
I reproduced using the same code: yaml.load('Foo: !Ref bar')
This worked for me :yaml.load('Foo: !Ref bar', Loader=yaml.BaseLoader)
@maru-podmast do you have some code to reproduce?
PS- this seems to work fine for me as of 5.2b1:
[root@1ee3dc7c3d7f pyyaml]# /opt/python/cp37-cp37m/bin/python
Python 3.7.5 (default, Nov 27 2019, 12:25:51)
[GCC 8.3.1 20190311 (Red Hat 8.3.1-3)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import yaml
>>>
>>> class Monster(yaml.YAMLObject):
... yaml_tag = u'!Monster'
... def __init__(self, name, hp, ac, attacks):
... self.name = name
... self.hp = hp
... self.ac = ac
... self.attacks = attacks
... def __repr__(self):
... return "%s(name=%r, hp=%r, ac=%r, attacks=%r)" % (
... self.__class__.__name__, self.name, self.hp, self.ac, self.attacks)
...
>>> yaml.unsafe_load("""
... --- !Monster
... name: Cave spider
... hp: [2,6] # 2d6
... ac: 16
... attacks: [BITE, HURT]
... """)
Monster(name='Cave spider', hp=[2, 6], ac=16, attacks=['BITE', 'HURT'])
>>>
@maru-podmast sorry, I can't reproduce. the original code works for me with 5.2b1 and 5.2:
yaml.load('Foo: !Ref bar', Loader=yaml.Loader)
yaml.load('Foo: !Ref bar', Loader=yaml.FullLoader)
yaml.load('Foo: !Ref bar') # emits warning
Released 5.2. Please reopen if necessary
@perlpunk This isn't working for me using the example you provided. I'm seeing the same results as @maru-podmast. What are we missing? It does work with BaseLoader.
>>> yaml.__version__
'5.2'
>>> yaml.load('Foo: !Ref bar', Loader=yaml.Loader)
Traceback (most recent call last):
...
...
... /python3.7/site-packages/yaml/constructor.py", line 420, in construct_undefined
node.start_mark)
yaml.constructor.ConstructorError: could not determine a constructor for the tag '!Ref'
in "<unicode string>", line 1, column 6:
Foo: !Ref bar
I'm on Python 3.7.4
@BonnieH @maru-podmast
I can only reproduce this without using the original code at the top of the issue.
Can you execute this code and show the output please?
import yaml
class Ref(yaml.YAMLObject):
yaml_tag = '!Ref'
def __init__(self, val):
self.val = val
@classmethod
def from_yaml(cls, loader, node):
return cls(node.value)
print(yaml.__version__)
data = yaml.load('Foo: !Ref bar', yaml.Loader)
print(data)
print(data['Foo'].val)
Without that class Ref of course it can't work. BaseLoader simply ignores the unknown tags.
@perlpunk This was a misunderstanding on my part, I hadn't defined the Ref class in my example. So it works now! And my real code is working now too, thanks for your help.
I'm using version 5.3 like so:
import yaml
yaml.load("mgnl:variationOf: !weakreference 721ec351-e73a-489e-b467-e9d608468ebd", Loader=yaml.Loader)
But I still got the same error.
yaml.constructor.ConstructorError: could not determine a constructor for the tag '!weakreference'
in "<unicode string>", line 1, column 19:
mgnl:variationOf: !weakreference 721ec351-e73a-489 ...
I resolved the issue by following https://github.com/yaml/pyyaml/issues/266#issuecomment-559116876.
yaml.load("mgnl:variationOf: !weakreference 721ec351-e73a-489e-b467-e9d608468ebd", Loader=yaml.BaseLoader)
@ryanbrookepayne BaseLoader only works because it is ignoring the weakreference tag.
To do it correctly, you would have to use the loader for which you added the constructor.
Same error for me. Worked using:
yaml.load('Foo: !Ref bar', Loader=yaml.BaseLoader)
Python 3.8.2
PyYAML 5.3.1
Most helpful comment
Try
I'm not sure though if this is intentional.
Will have a closer look later.