Repository: conda/conda-build

Issue:
Regression: version in meta.yaml, trailing zero truncated
<!--
Thanks for opening an issue! A few things to keep in mind:

- This issue tracker is for issues with or enhancements for conda-build.

For conda issues, you should open an issue at https://github.com/conda/conda/issues
For Anaconda issues, you should open an issue at https://github.com/ContinuumIO/anaconda-issues/issues
For an issue with a particular conda-forge package, you should open an issue on the 
corresponding feedstock: https://github.com/conda-forge
-->

### Actual Behavior

Trailing zeros on version number are truncated when rendering recipes, leading to incorrect versioning.

### Expected Behavior
Version is parsed correctly

### Steps to Reproduce

this script illustrates the issue on the function **yamlize** in metadata.py **l.203**

```python
import yaml

# version picked as string
ok = '''
package:
  name: test
  version: '2.10'
'''

# 2.10 picked as float => 2.1
nok = '''
package:
  name: test
  version: 2.10
'''

print(yaml.load(ok))
print(yaml.load(nok))
```
**Output**
```python
{'package': {'name': 'test', 'version': '2.10'}}
{'package': {'name': 'test', 'version': 2.1}}
```

**Workaround ?**
```diff
--- metadata.py	2018-05-22 18:02:44.837579000 +0200
+++ metadata_.py	2018-05-22 18:03:24.845777732 +0200
@@ -202,7 +202,7 @@
 
 def yamlize(data):
     try:
-        return yaml.load(data)
+        return yaml.load(data, Loader=yaml.BaseLoader)
     except yaml.error.YAMLError as e:
         if '{{' in data:
             try:
```

##### `Output of conda info`
<!-- Between the ticks below, paste the output of 'conda info' -->
```
     active environment : None
       user config file : $HOME/.condarc
 populated config files : $HOME/.condarc
          conda version : 4.5.4
    conda-build version : 3.10.4
         python version : 3.6.4.final.0
       base environment : $HOME/opt/conda3  (writable)
           channel URLs : https://repo.anaconda.com/pkgs/main/linux-64
                          https://repo.anaconda.com/pkgs/main/noarch
                          https://repo.anaconda.com/pkgs/free/linux-64
                          https://repo.anaconda.com/pkgs/free/noarch
                          https://repo.anaconda.com/pkgs/r/linux-64
                          https://repo.anaconda.com/pkgs/r/noarch
                          https://repo.anaconda.com/pkgs/pro/linux-64
                          https://repo.anaconda.com/pkgs/pro/noarch
          package cache : $HOME/opt/conda3/pkgs
                          $HOME/.conda/pkgs
       envs directories : $HOME/opt/conda3/envs
                          $HOME/.conda/envs
               platform : linux-64
             user-agent : conda/4.5.4 requests/2.18.4 CPython/3.6.4 Linux/4.15.0-22-generic ubuntu/18.04 glibc/2.27
                UID:GID : <...>:<...>
             netrc file : None
           offline mode : False
```

conda build `3.10.4`



Discussion:
Thanks for reporting.  I changed the loader and that screwed this up.  Will fix ASAP.
Thanks, seemed like a regression at first glance.

Resolving patch:
diff --git a/conda_build/metadata.py b/conda_build/metadata.py
--- a/conda_build/metadata.py
+++ b/conda_build/metadata.py
@@ -1,6 +1,7 @@
 from __future__ import absolute_import, division, print_function
 
 from collections import OrderedDict
+import contextlib
 import copy
 import hashlib
 import json
@@ -32,6 +33,13 @@
     sys.exit('Error: could not import yaml (required to read meta.yaml '
              'files of conda recipes)')
 
+try:
+    loader = yaml.CLoader
+except:
+    loader = yaml.Loader
+
+from yaml.resolver import Resolver
+
 on_win = (sys.platform == 'win32')
 
 # arches that don't follow exact names in the subdir need to be mapped here
@@ -202,7 +210,9 @@ def select_lines(data, namespace, variants_in_place):
 
 def yamlize(data):
     try:
-        return yaml.load(data)
+        with stringify_numbers():
+            loaded_data = yaml.load(data, Loader=loader)
+        return loaded_data
     except yaml.error.YAMLError as e:
         if '{{' in data:
             try:
@@ -786,6 +796,18 @@ def trim_build_only_deps(metadata, requirements_used):
     return requirements_used - to_remove
 
 
+@contextlib.contextmanager
+def stringify_numbers():
+    # ensure that numbers are not interpreted as ints or floats.  That trips up versions
+    #     with trailing zeros.
+    implicit_resolver_backup = Resolver.yaml_implicit_resolvers.copy()
+    for ch in list(u'-+0123456789'):
+        del Resolver.yaml_implicit_resolvers[ch]
+    yield
+    for ch in list(u'-+0123456789'):
+        Resolver.yaml_implicit_resolvers[ch] = implicit_resolver_backup[ch]
+
+
 class MetaData(object):
     def __init__(self, path, config=None, variant=None):
 


Test patch:
diff --git a/tests/test-recipes/metadata/float_misinterpretation/meta.yaml b/tests/test-recipes/metadata/float_misinterpretation/meta.yaml
new file mode 100644
--- /dev/null
+++ b/tests/test-recipes/metadata/float_misinterpretation/meta.yaml
@@ -0,0 +1,5 @@
+# test ensuring that version numbers that look like floating point numbers are kept as strings
+
+package:
+  name: test_floating_point_version
+  version: 1.10
diff --git a/tests/test-recipes/metadata/float_misinterpretation/run_test.bat b/tests/test-recipes/metadata/float_misinterpretation/run_test.bat
new file mode 100644
--- /dev/null
+++ b/tests/test-recipes/metadata/float_misinterpretation/run_test.bat
@@ -0,0 +1,4 @@
+if not "%PKG_VERSION%" == "1.10" (
+   echo PKG_VERSION is %PKG_VERSION%; should be 1.10
+   exit 1
+)
\ No newline at end of file
diff --git a/tests/test-recipes/metadata/float_misinterpretation/run_test.sh b/tests/test-recipes/metadata/float_misinterpretation/run_test.sh
new file mode 100644
--- /dev/null
+++ b/tests/test-recipes/metadata/float_misinterpretation/run_test.sh
@@ -0,0 +1,4 @@
+if [ "$PKG_VERSION" != "1.10" ]; then
+    echo "PKG_VERSION is $PKG_VERSION, but should be 1.10"
+    exit 1
+ fi