Skip to content

Instantly share code, notes, and snippets.

@jpassaro
Created November 17, 2017 17:07
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpassaro/4d5812290cdca51a8d3fe03c499d4149 to your computer and use it in GitHub Desktop.
Save jpassaro/4d5812290cdca51a8d3fe03c499d4149 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
from decimal import Decimal
import re
import yaml
from yaml.composer import Composer
from yaml.constructor import SafeConstructor
from yaml.parser import Parser
from yaml.reader import Reader
from yaml.resolver import BaseResolver, Resolver as DefaultResolver
from yaml.scanner import Scanner
class Resolver(BaseResolver):
pass
Resolver.add_implicit_resolver( # regex copied from yaml source
'!decimal',
re.compile(r'''^(?:
[-+]?(?:[0-9][0-9_]*)\.[0-9_]*(?:[eE][-+][0-9]+)?
|\.[0-9_]+(?:[eE][-+][0-9]+)?
|[-+]?[0-9][0-9_]*(?::[0-9]?[0-9])+\.[0-9_]*
|[-+]?\.(?:inf|Inf|INF)
|\.(?:nan|NaN|NAN)
)$''', re.VERBOSE),
list('-+0123456789.')
)
for ch, vs in DefaultResolver.yaml_implicit_resolvers.items():
Resolver.yaml_implicit_resolvers.setdefault(ch, []).extend(
(tag, regexp) for tag, regexp in vs
if not tag.endswith('float')
)
class Loader(Reader, Scanner, Parser, Composer, SafeConstructor, Resolver):
def __init__(self, stream):
Reader.__init__(self, stream)
Scanner.__init__(self)
Parser.__init__(self)
Composer.__init__(self)
SafeConstructor.__init__(self)
Resolver.__init__(self)
def decimal_constructor(loader, node):
value = loader.construct_scalar(node)
return Decimal(value)
yaml.add_constructor('!decimal', decimal_constructor, Loader)
def load(stream, **kwargs):
return yaml.load(stream, Loader, **kwargs)
if __name__ == '__main__':
from io import StringIO
doc = StringIO('foo: 0.1000')
expected = {'foo': Decimal('0.1')}
print('equal with yaml.load (expect False):', yaml.load(doc) == expected)
doc.seek(0)
print('equal with custom load (expect True):', load(doc) == expected)
@jpassaro
Copy link
Author

written in python 3; if you need for python 2, just omit from if __name__ == '__main__': on and you should be fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment