Repository: conda/conda-build

Issue:
MetaData.build_number()
Looking at the `build_number` method:
https://github.com/conda/conda-build/blob/cbc2428bdc09bf9eb0d855dc476fb7c0b164dcea/conda_build/metadata.py#L1174-L1181

I've reviewed the history of this method and see that it's been improved over the years to better work with jinja. I also see that in the current state most uses of this method (4 out of 6) do something like `meta.build_number() or 0`.

I have 2 observations:
1. In the current implementation it would appear that if a completely bad build value is provided (e.g. 'abba') then it will silently be accepted (unless there's a check elsewhere I haven't found yet). Is this desired or should a smarter check be done? 
2. I think it would be wise to return 0 instead of an empty string when receiving a falsy value.

Something like if build number is `None`/missing then return 0 (this seems to satisfy stuff happening with jinja templating, see blame history) else if build number is non-`int` raise error.


Discussion:

Resolving patch:
diff --git a/conda_build/environ.py b/conda_build/environ.py
--- a/conda_build/environ.py
+++ b/conda_build/environ.py
@@ -491,7 +491,7 @@ def meta_vars(meta, skip_build_id=False):
     # use `get_value` to prevent early exit while name is still unresolved during rendering
     d['PKG_NAME'] = meta.get_value('package/name')
     d['PKG_VERSION'] = meta.version()
-    d['PKG_BUILDNUM'] = str(meta.build_number() or 0)
+    d['PKG_BUILDNUM'] = str(meta.build_number())
     if meta.final and not skip_build_id:
         d['PKG_BUILD_STRING'] = str(meta.build_id())
         d['PKG_HASH'] = meta.hash_dependencies()
diff --git a/conda_build/metadata.py b/conda_build/metadata.py
--- a/conda_build/metadata.py
+++ b/conda_build/metadata.py
@@ -591,7 +591,7 @@ def build_string_from_metadata(metadata):
             res.append('_')
         if features:
             res.extend(('_'.join(features), '_'))
-        res.append('{0}'.format(metadata.build_number() if metadata.build_number() else 0))
+        res.append(str(metadata.build_number()))
         build_str = "".join(res)
     return build_str
 
@@ -1173,12 +1173,15 @@ def version(self):
 
     def build_number(self):
         number = self.get_value('build/number')
+
         # build number can come back as None if no setting (or jinja intermediate)
+        if not number:
+            return 0
+
         try:
-            build_int = int(number)
+            return int(number)
         except (ValueError, TypeError):
-            build_int = ""
-        return build_int
+            raise ValueError("Build number was invalid value '{}'. Must be an integer.".format(number))
 
     def get_depends_top_and_out(self, typ):
         meta_requirements = ensure_list(self.get_value('requirements/' + typ, []))[:]
@@ -1370,7 +1373,7 @@ def info_index(self):
             name=self.name(),
             version=self.version(),
             build=self.build_id(),
-            build_number=self.build_number() if self.build_number() else 0,
+            build_number=self.build_number(),
             platform=self.config.host_platform if (self.config.host_platform != 'noarch' and
                                                    arch != 'noarch') else None,
             arch=ARCH_MAP.get(arch, arch),
diff --git a/conda_build/utils.py b/conda_build/utils.py
--- a/conda_build/utils.py
+++ b/conda_build/utils.py
@@ -1898,7 +1898,7 @@ def match_peer_job(target_matchspec, other_m, this_m=None):
                                               match_dict['build'])),
                           version=match_dict['version'],
                           build_string=match_dict['build'],
-                          build_number=int(other_m.build_number() or 0),
+                          build_number=other_m.build_number(),
                           channel=None)
     matchspec_matches = target_matchspec.match(match_dict)
 


Test patch: