def setUp(self):
        super(TestTemplatePath, self).setUp()

        # Make various types of keys(fields)
        self.keys = {
            "Sequence": StringKey("Sequence"),
            "Shot": StringKey("Shot",
                              default="s1",
                              choices=["s1", "s2", "shot_1"]),
            "Step": StringKey("Step"),
            "branch": StringKey("branch", filter_by="alphanumeric"),
            "name": StringKey("name"),
            "version": IntegerKey("version", format_spec="03"),
            "snapshot": IntegerKey("snapshot", format_spec="03"),
            "ext": StringKey("ext"),
            "seq_num": SequenceKey("seq_num"),
            "frame": SequenceKey("frame", format_spec="04")
        }
        # Make a template
        self.definition = "shots/{Sequence}/{Shot}/{Step}/work/{Shot}.{branch}.v{version}.{snapshot}.ma"
        self.template_path = TemplatePath(self.definition, self.keys,
                                          self.project_root)

        # make template with sequence key
        self.sequence = TemplatePath("/path/to/seq.{frame}.ext", self.keys, "",
                                     "frame")
Example #2
0
    def setUp(self):
        super(TestTemplate, self).setUp()

        # Make various types of keys(fields)
        self.keys = {
            "Sequence":
            StringKey("Sequence"),
            "Shot":
            StringKey("Shot", default="s1", choices=["s1", "s2", "shot_1"]),
            "Step":
            StringKey("Step"),
            "branch":
            StringKey("branch", filter_by="alphanumeric"),
            "name":
            StringKey("name"),
            "version":
            IntegerKey("version", format_spec="03"),
            "snapshot":
            IntegerKey("snapshot", format_spec="03"),
            "ext":
            StringKey("ext"),
            "seq_num":
            SequenceKey("seq_num"),
            "frame":
            SequenceKey("frame", format_spec="04"),
            "day_month_year":
            TimestampKey("day_month_year", format_spec="%d_%m_%Y")
        }
        # Make a template
        self.definition = "shots/{Sequence}/{Shot}/{Step}/work/{Shot}.{branch}.v{version}.{snapshot}.{day_month_year}.ma"
        self.template = Template(self.definition, self.keys)
Example #3
0
    def setUp(self):
        super(TestTemplatePath, self).setUp(
            parameters={"primary_root_name": "primary_with_a_different_name"})
        # Make various types of keys(fields)
        self.keys = {
            "Sequence": StringKey("Sequence"),
            "Shot": StringKey("Shot",
                              default="s1",
                              choices=["s1", "s2", "shot_1"]),
            "Step": StringKey("Step"),
            "branch": StringKey("branch", filter_by="alphanumeric"),
            "name": StringKey("name"),
            "name_alpha": StringKey("name_alpha", filter_by="alphanumeric"),
            "version": IntegerKey("version", format_spec="03"),
            "snapshot": IntegerKey("snapshot", format_spec="03"),
            "ext": StringKey("ext"),
            "seq_num": SequenceKey("seq_num"),
            "frame": SequenceKey("frame", format_spec="04"),
        }
        # Make a template
        self.definition = "shots/{Sequence}/{Shot}/{Step}/work/{Shot}.{branch}.v{version}.{snapshot}.ma"

        # legacy style template object which only knows about the currently running operating system
        self.template_path_current_os_only = TemplatePath(
            self.definition, self.keys, self.project_root)

        project_root = os.path.join(self.tank_temp, "project_code")
        self._project_roots = {self.primary_root_name: {}}
        # Create the roots.yml like structure. Double down on the key names so it can be used in all scenarios
        # where we require the roots.
        for os_name in [
                "windows_path",
                "linux_path",
                "mac_path",
                "win32",
                "linux2",
                "darwin",
        ]:
            self._project_roots[self.primary_root_name][os_name] = project_root
        self._primary_project_root = project_root

        # new style template object which supports all recognized platforms
        # get all OS roots for primary storage
        all_roots = self._project_roots[self.primary_root_name]

        self.template_path = TemplatePath(self.definition,
                                          self.keys,
                                          self.project_root,
                                          per_platform_roots=all_roots)

        self.project_root_template = TemplatePath("/",
                                                  self.keys,
                                                  self.project_root,
                                                  per_platform_roots=all_roots)

        # make template with sequence key
        self.sequence = TemplatePath("/path/to/seq.{frame}.ext", self.keys, "",
                                     "frame")
Example #4
0
    def _test_non_strict_matching(self, padding_char):
        """
        Allows to test strict matching with a specific padding character.

        :param padding_char: Character to test padding with. Should be space or 0.
        """
        key = IntegerKey("version_number", format_spec="%s3" % padding_char, strict_matching=False)

        # The padding char is missing in the format specifier, but we still need when validating
        # results.
        if padding_char == '':
            padding_char = ' '

        # It should match because they are valid numbers.

        self.assertEqual(key.value_from_str("000"), 0)
        self.assertEqual(key.value_from_str("0"), 0)
        self.assertEqual(key.value_from_str("0"), 0)

        # While the number doesn't make any sense as far as formatting is concerned, this used
        # to work in old versions of Toolkit and needs to keep working in non strict mode.
        self.assertEqual(key.value_from_str("%s000" % padding_char), 0)

        # It should match a template with too many digits...
        self.assertEqual(key.value_from_str("20000"), 20000)

        # ... even if they are all zeros because lossy matching.
        self.assertEqual(key.value_from_str("00000"), 0)

        # From path to tokens back to path should be lossy.
        value = key.value_from_str("1")
        self.assertEqual("%s%s1" % (padding_char, padding_char), key.str_from_value(value))

        self._test_nan(key, "expected an Integer")
    def _test_non_strict_matching(self, padding_char):
        """
        Allows to test strict matching with a specific padding character.

        :param padding_char: Character to test padding with. Should be space or 0.
        """
        key = IntegerKey("version_number", format_spec="%s3" % padding_char, strict_matching=False)

        # The padding char is missing in the format specifier, but we still need when validating
        # results.
        if padding_char == '':
            padding_char = ' '

        # It should match because they are valid numbers.

        self.assertEqual(key.value_from_str("000"), 0)
        self.assertEqual(key.value_from_str("0"), 0)
        self.assertEqual(key.value_from_str("0"), 0)

        # While the number doesn't make any sense as far as formatting is concerned, this used
        # to work in old versions of Toolkit and needs to keep working in non strict mode.
        self.assertEqual(key.value_from_str("%s000" % padding_char), 0)

        # It should match a template with too many digits...
        self.assertEqual(key.value_from_str("20000"), 20000)

        # ... even if they are all zeros because lossy matching.
        self.assertEqual(key.value_from_str("00000"), 0)

        # From path to tokens back to path should be lossy.
        value = key.value_from_str("1")
        self.assertEqual("%s%s1" % (padding_char, padding_char), key.str_from_value(value))

        self._test_nan(key, "expected an Integer")
Example #6
0
 def test_ambiguous_wrong_type(self):
     keys = {
         "some_num": IntegerKey("some_num"),
         "other_num": IntegerKey("other_num")
     }
     self.keys.update(keys)
     definition = "build/{Asset}_{some_num}_{other_num}.{ext}"
     input_path = "build/cat_1_man_14_2.jpeg"
     expected = {
         "Asset": "cat_1_man",
         "some_num": 14,
         "other_num": 2,
         "ext": "jpeg"
     }
     self.assert_path_matches(definition, input_path, expected)
Example #7
0
    def setUp(self):
        super(TestPathsFromTemplateGlob, self).setUp()
        keys = {"Shot": StringKey("Shot"),
                "version": IntegerKey("version", format_spec="03"),
                "seq_num": SequenceKey("seq_num", format_spec="05")}

        self.template = TemplatePath("{Shot}/{version}/filename.{seq_num}", keys, root_path=self.project_root)
Example #8
0
    def test_skip_invalid(self):
        """Test that files not valid for an template are not returned.

        This refers to bug reported in Ticket #17090
        """
        keys = {
            "Shot": StringKey("Shot"),
            "Sequence": StringKey("Sequence"),
            "Step": StringKey("Step"),
            "name": StringKey("name"),
            "version": IntegerKey("version", format_spec="03")
        }

        definition = "sequences/{Sequence}/{Shot}/{Step}/work/{name}.v{version}.nk"
        template = TemplatePath(definition, keys, self.project_root,
                                "my_template")
        tk = tank.Tank(self.project_root)
        tk._templates = {template.name: template}
        bad_file_path = os.path.join(self.project_root, "sequences",
                                     "Sequence1", "Shot1", "Foot", "work",
                                     "name1.va.nk")
        good_file_path = os.path.join(self.project_root, "sequences",
                                      "Sequence1", "Shot1", "Foot", "work",
                                      "name.v001.nk")
        self.create_file(bad_file_path)
        self.create_file(good_file_path)
        ctx_fields = {"Sequence": "Sequence1", "Shot": "Shot1", "Step": "Foot"}
        result = tk.paths_from_template(template, ctx_fields)
        self.assertIn(good_file_path, result)
        self.assertNotIn(bad_file_path, result)
Example #9
0
 def test_template_query_invalid(self):
     """
     Check case that value returned from shotgun is invalid.
     """
     query_key = IntegerKey("shot_seq", shotgun_entity_type="Shot", shotgun_field_name="sg_sequence")
     self.keys["shot_seq"] = query_key
     template_def = "/sequence/{Sequence}/{Shot}/{Step}/work/{shot_seq}.ext"
     template = TemplatePath(template_def, self.keys, self.project_root)
     self.assertRaises(TankError, self.ctx.as_template_fields, template)
Example #10
0
 def test_aliased_key(self):
     key = IntegerKey("aliased_name")
     keys = {"initial_name": key}
     definition = "{initial_name}"
     template = TemplatePath(definition, keys, self.project_root)
     input_path = os.path.join(self.project_root, "3")
     expected = {"aliased_name": 3}
     result = template.get_fields(input_path)
     self.assertEquals(expected, result)
Example #11
0
 def setUp(self):
     super(TestTemplateString, self).setUp()
     self.keys = {
         "Sequence": StringKey("Sequence"),
         "Shot": StringKey("Shot"),
         "version": IntegerKey("version"),
     }
     self.template_string = TemplateString("something-{Shot}.{Sequence}",
                                           self.keys)
Example #12
0
    def setUp(self):
        super(TestTemplatePath, self).setUp()

        # Make various types of keys(fields)
        self.keys = {
            "Sequence": StringKey("Sequence"),
            "Shot": StringKey("Shot",
                              default="s1",
                              choices=["s1", "s2", "shot_1"]),
            "Step": StringKey("Step"),
            "branch": StringKey("branch", filter_by="alphanumeric"),
            "name": StringKey("name"),
            "name_alpha": StringKey("name_alpha", filter_by="alphanumeric"),
            "version": IntegerKey("version", format_spec="03"),
            "snapshot": IntegerKey("snapshot", format_spec="03"),
            "ext": StringKey("ext"),
            "seq_num": SequenceKey("seq_num"),
            "frame": SequenceKey("frame", format_spec="04")
        }
        # Make a template
        self.definition = "shots/{Sequence}/{Shot}/{Step}/work/{Shot}.{branch}.v{version}.{snapshot}.ma"

        # legacy style template object which only knows about the currently running operating system
        self.template_path_current_os_only = TemplatePath(
            self.definition, self.keys, self.project_root)

        # new style template object which supports all recognized platforms
        # get all OS roots for primary storage
        all_roots = self.pipeline_configuration.get_all_platform_data_roots(
        )["primary"]

        self.template_path = TemplatePath(self.definition,
                                          self.keys,
                                          self.project_root,
                                          per_platform_roots=all_roots)

        self.project_root_template = TemplatePath("/",
                                                  self.keys,
                                                  self.project_root,
                                                  per_platform_roots=all_roots)

        # make template with sequence key
        self.sequence = TemplatePath("/path/to/seq.{frame}.ext", self.keys, "",
                                     "frame")
Example #13
0
 def test_double_int_key(self):
     """Test case that key of type int appears twice in definition."""
     int_key = IntegerKey("int_key")
     definition = "{int_key}/something/{int_key}.else"
     template = TemplatePath(definition, {"int_key": int_key},
                             root_path=self.project_root)
     expected = {"int_key": 4}
     relative_path = "4/something/4.else"
     input_path = os.path.join(self.project_root, relative_path)
     actual = template.get_fields(input_path)
     self.assertEquals(expected, actual)
Example #14
0
    def test_aliased_key(self):
        """
        Apply values to a template which has an aliased key.
        """
        key = IntegerKey("aliased_name")
        keys = {"initial_name": key}
        definition = "{initial_name}"
        template = TemplatePath(definition, keys, self.project_root)

        expected = os.path.join(self.project_root, "2")
        fields = {"aliased_name": 2}
        self.assertEquals(expected, template.apply_fields(fields))

        fields = {"initial_name": 2}
        self.assertRaises(TankError, template.apply_fields, fields)
class TestIntegerKey(ShotgunTestBase):
    def setUp(self):
        super(TestIntegerKey, self).setUp()
        self.int_field = IntegerKey("field_name")

    def test_bad_default(self):
        """Case that specified default does not match type."""
        default_value = "default_value"
        self.assertRaises(TankError, IntegerKey, "field_name", default=default_value)

    def test_illegal_choice(self):
        """Choice conflict with type."""
        choices_value = ["a", "b"]
        self.assertRaises(TankError, IntegerKey, "field_name", choices=choices_value)

    def test_format_set(self):
        format_spec = "03"
        template_field = IntegerKey("field_name", format_spec=format_spec)
        self.assertEqual(format_spec, template_field.format_spec)

    def test_validate_string_good(self):
        value = "23"
        self.assertTrue(self.int_field.validate(value))

    def test_validate_int_good(self):
        value = 23
        self.assertTrue(self.int_field.validate(value))

    def test_validate_bad(self):
        value = "a"
        self.assertFalse(self.int_field.validate(value))

    def test_str_from_value_good(self):
        value = 3
        expected = "%s" % value
        result = self.int_field.str_from_value(value)
        self.assertEqual(expected, result)

    def test_str_from_value_zero(self):
        value = 0
        expected = "%d" % value
        result = self.int_field.str_from_value(value)
        self.assertEqual(expected, result)

    def test_str_from_value_bad(self):
        value = "a"
        expected = "%s Illegal value '%s', expected an Integer" % (str(self.int_field), value)
        self.check_error_message(TankError, expected, self.int_field.str_from_value, value)

    def test_str_from_value_formatted(self):
        formatted_field = IntegerKey("field_name", format_spec="03")
        value = 3
        expected = "%03d" % value
        result = formatted_field.str_from_value(value)
        self.assertEqual(expected, result)

    def test_str_from_value_ignore_type(self):
        value = "a"
        expected = value
        result = self.int_field.str_from_value(value, ignore_type=True)
        self.assertEqual(expected, result)

    def test_value_from_str(self):
        str_value = "32"
        self.assertEqual(32, self.int_field.value_from_str(str_value))

    def test_repr(self):
        expected = "<Sgtk IntegerKey field_name>"
        self.assertEqual(expected, str(self.int_field))

    def test_init_validation(self):
        """
        Makes sure that parameter validation is correct in the constructor.
        """
        # This should obviously work
        self._validate_key(
            IntegerKey("version_number"),
            strict_matching=None, format_spec=None
        )
        # When specifying parameters, they should be set accordingly.
        self._validate_key(
            IntegerKey("version_number", format_spec="03", strict_matching=True),
            strict_matching=True, format_spec="03"
        )
        self._validate_key(
            IntegerKey("version_number", format_spec="03", strict_matching=False),
            strict_matching=False, format_spec="03"
        )
        self._validate_key(
            IntegerKey("version_number", format_spec="3", strict_matching=False),
            strict_matching=False, format_spec="3"
        )
        # When specifying a format but not specifying the strict_matching, it should
        # still have strict_matching.
        self._validate_key(
            IntegerKey("version_number", format_spec="03"),
            strict_matching=True, format_spec="03"
        )
        # Make sure than an error is raised when wrong types are passed in.
        with self.assertRaisesRegex(TankError, "is not of type boolean"):
            IntegerKey("version_number", strict_matching=1)

        with self.assertRaisesRegex(TankError, "is not of type string"):
            IntegerKey("version_number", format_spec=1)

        # Make sure that if the user specifies strict_matching with no format
        # there is an error
        error_regexp = "strict_matching can't be set"
        with self.assertRaisesRegex(TankError, error_regexp):
            IntegerKey("version_number", strict_matching=False)

        with self.assertRaisesRegex(TankError, error_regexp):
            IntegerKey("version_number", strict_matching=True)

        # We support 4 format_spec values:
        # - None
        # - non zero positive number
        # - zero followed by a non zero positive number
        IntegerKey("version_number", format_spec=None)
        IntegerKey("version_number", format_spec="1")
        IntegerKey("version_number", format_spec="01")

        # Make sure invalid formats are caught
        with self.assertRaisesRegex(TankError, "format_spec can't be empty"):
            IntegerKey("version_number", format_spec="")

        error_regexp = "has to either be"
        # We don't support the sign option.
        with self.assertRaisesRegex(TankError, error_regexp):
            IntegerKey("version_number", format_spec=" 3", strict_matching=False)

        with self.assertRaisesRegex(TankError, error_regexp):
            # Should throw because the padding number is not non zero.
            IntegerKey("version_number", format_spec="00")

        with self.assertRaisesRegex(TankError, error_regexp):
            # Should throw because it is not a non zero positive integer
            IntegerKey("version_number", format_spec="0")

        with self.assertRaisesRegex(TankError, error_regexp):
            # Should throw because the padding caracter is invalid
            IntegerKey("version_number", format_spec="a0")

        with self.assertRaisesRegex(TankError, error_regexp):
            # Should throw because the padding size is not a number.
            IntegerKey("version_number", format_spec="0a")

    def test_no_format_spec(self):
        key = IntegerKey("version_number")
        key.value_from_str

    def _validate_key(self, key, strict_matching, format_spec):
        """
        Makes sure that an integer key's formatting options are correctly set.
        """
        self.assertEqual(key.strict_matching, strict_matching)
        self.assertEqual(key.format_spec, format_spec)

    def test_non_strict_matching(self):
        """
        In non strict mode, tokens can actually have less numbers than the padding requests. Also,
        if there are more, can also match.
        """
        self._test_non_strict_matching('0')
        self._test_non_strict_matching('')

    def _test_non_strict_matching(self, padding_char):
        """
        Allows to test strict matching with a specific padding character.

        :param padding_char: Character to test padding with. Should be space or 0.
        """
        key = IntegerKey("version_number", format_spec="%s3" % padding_char, strict_matching=False)

        # The padding char is missing in the format specifier, but we still need when validating
        # results.
        if padding_char == '':
            padding_char = ' '

        # It should match because they are valid numbers.

        self.assertEqual(key.value_from_str("000"), 0)
        self.assertEqual(key.value_from_str("0"), 0)
        self.assertEqual(key.value_from_str("0"), 0)

        # While the number doesn't make any sense as far as formatting is concerned, this used
        # to work in old versions of Toolkit and needs to keep working in non strict mode.
        self.assertEqual(key.value_from_str("%s000" % padding_char), 0)

        # It should match a template with too many digits...
        self.assertEqual(key.value_from_str("20000"), 20000)

        # ... even if they are all zeros because lossy matching.
        self.assertEqual(key.value_from_str("00000"), 0)

        # From path to tokens back to path should be lossy.
        value = key.value_from_str("1")
        self.assertEqual("%s%s1" % (padding_char, padding_char), key.str_from_value(value))

        self._test_nan(key, "expected an Integer")

    def _test_nan(self, key, error_msg):
        """
        Tests a key with against values that are not numbers.

        :param key: Key to test.
        :param error_msg: Text that partially matches the error message.
        """
        # Should fail because not a number
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("aaaa")
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("0a")
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("a0")
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("aa")

    def _test_strict_matching(self, padding_char):
        """
        Allows to test strict matching with any padding type.
        """
        # have a template that formats with two digits of padding.
        key = IntegerKey("version_number", format_spec="%s3" % padding_char, strict_matching=True)
        self.assertTrue(key.strict_matching)

        # The padding char is missing in the format specifier, but we still need when validating
        # results.
        if padding_char == '':
            padding_char = ' '

        # From path to tokens back to path should get back the same string when the expected number of
        # digits are found.
        value = key.value_from_str("%s%s1" % (padding_char, padding_char))
        self.assertEqual("%s%s1" % (padding_char, padding_char), key.str_from_value(value))

        # It should match a template with more digits.
        value = key.value_from_str("20000")
        self.assertEqual("20000", key.str_from_value(value))

        key.value_from_str("123")

        error_msg = "does not match format spec"

        # It should not match a string with too few digits
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("1")

        # It should not match a template with too many digits that are all zero because that would
        # lossy. (there are more zeros than the format spec can rebuild)
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("0000")

        # It should not match negative numbers either
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("-1000")

        # It should not match baddly padded numbers
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("0100")

        # It should not match negative values
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("-01")

        self._test_nan(key, error_msg)

    def test_strict_matching(self):
        """
        In strict mode, tokens have to have as much padding as the format specifier suggests. Less will not
        match.
        """
        self._test_strict_matching('')
        self._test_strict_matching('0')
Example #16
0
 def test_str_from_value_formatted(self):
     formatted_field = IntegerKey("field_name", format_spec="03")
     value = 3
     expected = "%03d" % value
     result = formatted_field.str_from_value(value)
     self.assertEquals(expected, result)
Example #17
0
 def test_format_set(self):
     format_spec = "03"
     template_field = IntegerKey("field_name", format_spec=format_spec)
     self.assertEquals(format_spec, template_field.format_spec)
Example #18
0
 def setUp(self):
     super(TestIntegerKey, self).setUp()
     self.int_field = IntegerKey("field_name")
Example #19
0
class TestIntegerKey(TankTestBase):
    def setUp(self):
        super(TestIntegerKey, self).setUp()
        self.int_field = IntegerKey("field_name")

    def test_bad_default(self):
        """Case that specified default does not match type."""
        default_value = "default_value"
        self.assertRaises(TankError,
                          IntegerKey,
                          "field_name",
                          default=default_value)

    def test_illegal_choice(self):
        """Choice conflict with type."""
        choices_value = ["a", "b"]
        self.assertRaises(TankError,
                          IntegerKey,
                          "field_name",
                          choices=choices_value)

    def test_format_set(self):
        format_spec = "03"
        template_field = IntegerKey("field_name", format_spec=format_spec)
        self.assertEquals(format_spec, template_field.format_spec)

    def test_validate_string_good(self):
        value = "23"
        self.assertTrue(self.int_field.validate(value))

    def test_validate_int_good(self):
        value = 23
        self.assertTrue(self.int_field.validate(value))

    def test_validate_bad(self):
        value = "a"
        self.assertFalse(self.int_field.validate(value))

    def test_str_from_value_good(self):
        value = 3
        expected = "%s" % value
        result = self.int_field.str_from_value(value)
        self.assertEquals(expected, result)

    def test_str_from_value_zero(self):
        value = 0
        expected = "%d" % value
        result = self.int_field.str_from_value(value)
        self.assertEquals(expected, result)

    def test_str_from_value_bad(self):
        value = "a"
        expected = "%s Illegal value %s, expected an Integer" % (str(
            self.int_field), value)
        self.check_error_message(TankError, expected,
                                 self.int_field.str_from_value, value)

    def test_str_from_value_formatted(self):
        formatted_field = IntegerKey("field_name", format_spec="03")
        value = 3
        expected = "%03d" % value
        result = formatted_field.str_from_value(value)
        self.assertEquals(expected, result)

    def test_str_from_value_ignore_type(self):
        value = "a"
        expected = value
        result = self.int_field.str_from_value(value, ignore_type=True)
        self.assertEquals(expected, result)

    def test_value_from_str(self):
        str_value = "32"
        self.assertEquals(32, self.int_field.value_from_str(str_value))

    def test_repr(self):
        expected = "<Sgtk IntegerKey field_name>"
        self.assertEquals(expected, str(self.int_field))
Example #20
0
 def test_str_from_value_formatted(self):
     formatted_field = IntegerKey("field_name", format_spec="03")
     value = 3
     expected = "%03d" % value
     result = formatted_field.str_from_value(value)
     self.assertEquals(expected, result)
Example #21
0
class TestIntegerKey(TankTestBase):
    def setUp(self):
        super(TestIntegerKey, self).setUp()
        self.int_field = IntegerKey("field_name")

    def test_bad_default(self):
        """Case that specified default does not match type."""
        default_value = "default_value"
        self.assertRaises(TankError, IntegerKey, "field_name", default=default_value)

    def test_illegal_choice(self):
        """Choice conflict with type."""
        choices_value = ["a", "b"]
        self.assertRaises(TankError, IntegerKey, "field_name", choices=choices_value)

    def test_format_set(self):
        format_spec = "03"
        template_field = IntegerKey("field_name", format_spec=format_spec)
        self.assertEquals(format_spec, template_field.format_spec)

    def test_validate_string_good(self):
        value = "23"
        self.assertTrue(self.int_field.validate(value))

    def test_validate_int_good(self):
        value = 23
        self.assertTrue(self.int_field.validate(value))

    def test_validate_bad(self):
        value = "a"
        self.assertFalse(self.int_field.validate(value))

    def test_str_from_value_good(self):
        value = 3
        expected = "%s" % value
        result = self.int_field.str_from_value(value)
        self.assertEquals(expected, result)

    def test_str_from_value_zero(self):
        value = 0
        expected = "%d" % value
        result = self.int_field.str_from_value(value)
        self.assertEquals(expected, result)

    def test_str_from_value_bad(self):
        value = "a"
        expected = "%s Illegal value %s, expected an Integer" % (str(self.int_field), value)
        self.check_error_message(TankError, expected, self.int_field.str_from_value, value)

    def test_str_from_value_formatted(self):
        formatted_field = IntegerKey("field_name", format_spec="03")
        value = 3
        expected = "%03d" % value
        result = formatted_field.str_from_value(value)
        self.assertEquals(expected, result)

    def test_str_from_value_ignore_type(self):
        value = "a"
        expected = value
        result = self.int_field.str_from_value(value, ignore_type=True)
        self.assertEquals(expected, result)

    def test_value_from_str(self):
        str_value = "32"
        self.assertEquals(32, self.int_field.value_from_str(str_value))

    def test_repr(self):
        expected = "<Sgtk IntegerKey field_name>"
        self.assertEquals(expected, str(self.int_field))
Example #22
0
    def _test_strict_matching(self, padding_char):
        """
        Allows to test strict matching with any padding type.
        """
        # have a template that formats with two digits of padding.
        key = IntegerKey("version_number",
                         format_spec="%s3" % padding_char,
                         strict_matching=True)
        self.assertTrue(key.strict_matching)

        # The padding char is missing in the format specifier, but we still need when validating
        # results.
        if padding_char == "":
            padding_char = " "

        # From path to tokens back to path should get back the same string when the expected number of
        # digits are found.
        value = key.value_from_str("%s%s1" % (padding_char, padding_char))
        self.assertEqual("%s%s1" % (padding_char, padding_char),
                         key.str_from_value(value))

        # It should match a template with more digits.
        value = key.value_from_str("20000")
        self.assertEqual("20000", key.str_from_value(value))

        key.value_from_str("123")

        error_msg = "does not match format spec"

        # It should not match a string with too few digits
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("1")

        # It should not match a template with too many digits that are all zero because that would
        # lossy. (there are more zeros than the format spec can rebuild)
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("0000")

        # It should not match negative numbers either
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("-1000")

        # It should not match baddly padded numbers
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("0100")

        # It should not match negative values
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("-01")

        self._test_nan(key, error_msg)
Example #23
0
 def test_no_format_spec(self):
     key = IntegerKey("version_number")
     key.value_from_str
Example #24
0
class TestIntegerKey(ShotgunTestBase):
    def setUp(self):
        super(TestIntegerKey, self).setUp()
        self.int_field = IntegerKey("field_name")

    def test_bad_default(self):
        """Case that specified default does not match type."""
        default_value = "default_value"
        self.assertRaises(TankError,
                          IntegerKey,
                          "field_name",
                          default=default_value)

    def test_illegal_choice(self):
        """Choice conflict with type."""
        choices_value = ["a", "b"]
        self.assertRaises(TankError,
                          IntegerKey,
                          "field_name",
                          choices=choices_value)

    def test_format_set(self):
        format_spec = "03"
        template_field = IntegerKey("field_name", format_spec=format_spec)
        self.assertEqual(format_spec, template_field.format_spec)

    def test_validate_string_good(self):
        value = "23"
        self.assertTrue(self.int_field.validate(value))

    def test_validate_int_good(self):
        value = 23
        self.assertTrue(self.int_field.validate(value))

    def test_validate_bad(self):
        value = "a"
        self.assertFalse(self.int_field.validate(value))

    def test_str_from_value_good(self):
        value = 3
        expected = "%s" % value
        result = self.int_field.str_from_value(value)
        self.assertEqual(expected, result)

    def test_str_from_value_zero(self):
        value = 0
        expected = "%d" % value
        result = self.int_field.str_from_value(value)
        self.assertEqual(expected, result)

    def test_str_from_value_bad(self):
        value = "a"
        expected = "%s Illegal value '%s', expected an Integer" % (
            str(self.int_field),
            value,
        )
        self.check_error_message(TankError, expected,
                                 self.int_field.str_from_value, value)

    def test_str_from_value_formatted(self):
        formatted_field = IntegerKey("field_name", format_spec="03")
        value = 3
        expected = "%03d" % value
        result = formatted_field.str_from_value(value)
        self.assertEqual(expected, result)

    def test_str_from_value_ignore_type(self):
        value = "a"
        expected = value
        result = self.int_field.str_from_value(value, ignore_type=True)
        self.assertEqual(expected, result)

    def test_value_from_str(self):
        str_value = "32"
        self.assertEqual(32, self.int_field.value_from_str(str_value))

    def test_repr(self):
        expected = "<Sgtk IntegerKey field_name>"
        self.assertEqual(expected, str(self.int_field))

    def test_init_validation(self):
        """
        Makes sure that parameter validation is correct in the constructor.
        """
        # This should obviously work
        self._validate_key(IntegerKey("version_number"),
                           strict_matching=None,
                           format_spec=None)
        # When specifying parameters, they should be set accordingly.
        self._validate_key(
            IntegerKey("version_number",
                       format_spec="03",
                       strict_matching=True),
            strict_matching=True,
            format_spec="03",
        )
        self._validate_key(
            IntegerKey("version_number",
                       format_spec="03",
                       strict_matching=False),
            strict_matching=False,
            format_spec="03",
        )
        self._validate_key(
            IntegerKey("version_number",
                       format_spec="3",
                       strict_matching=False),
            strict_matching=False,
            format_spec="3",
        )
        # When specifying a format but not specifying the strict_matching, it should
        # still have strict_matching.
        self._validate_key(
            IntegerKey("version_number", format_spec="03"),
            strict_matching=True,
            format_spec="03",
        )
        # Make sure than an error is raised when wrong types are passed in.
        with self.assertRaisesRegex(TankError, "is not of type boolean"):
            IntegerKey("version_number", strict_matching=1)

        with self.assertRaisesRegex(TankError, "is not of type string"):
            IntegerKey("version_number", format_spec=1)

        # Make sure that if the user specifies strict_matching with no format
        # there is an error
        error_regexp = "strict_matching can't be set"
        with self.assertRaisesRegex(TankError, error_regexp):
            IntegerKey("version_number", strict_matching=False)

        with self.assertRaisesRegex(TankError, error_regexp):
            IntegerKey("version_number", strict_matching=True)

        # We support 4 format_spec values:
        # - None
        # - non zero positive number
        # - zero followed by a non zero positive number
        IntegerKey("version_number", format_spec=None)
        IntegerKey("version_number", format_spec="1")
        IntegerKey("version_number", format_spec="01")

        # Make sure invalid formats are caught
        with self.assertRaisesRegex(TankError, "format_spec can't be empty"):
            IntegerKey("version_number", format_spec="")

        error_regexp = "has to either be"
        # We don't support the sign option.
        with self.assertRaisesRegex(TankError, error_regexp):
            IntegerKey("version_number",
                       format_spec=" 3",
                       strict_matching=False)

        with self.assertRaisesRegex(TankError, error_regexp):
            # Should throw because the padding number is not non zero.
            IntegerKey("version_number", format_spec="00")

        with self.assertRaisesRegex(TankError, error_regexp):
            # Should throw because it is not a non zero positive integer
            IntegerKey("version_number", format_spec="0")

        with self.assertRaisesRegex(TankError, error_regexp):
            # Should throw because the padding caracter is invalid
            IntegerKey("version_number", format_spec="a0")

        with self.assertRaisesRegex(TankError, error_regexp):
            # Should throw because the padding size is not a number.
            IntegerKey("version_number", format_spec="0a")

    def test_no_format_spec(self):
        key = IntegerKey("version_number")
        key.value_from_str

    def _validate_key(self, key, strict_matching, format_spec):
        """
        Makes sure that an integer key's formatting options are correctly set.
        """
        self.assertEqual(key.strict_matching, strict_matching)
        self.assertEqual(key.format_spec, format_spec)

    def test_non_strict_matching(self):
        """
        In non strict mode, tokens can actually have less numbers than the padding requests. Also,
        if there are more, can also match.
        """
        self._test_non_strict_matching("0")
        self._test_non_strict_matching("")

    def _test_non_strict_matching(self, padding_char):
        """
        Allows to test strict matching with a specific padding character.

        :param padding_char: Character to test padding with. Should be space or 0.
        """
        key = IntegerKey("version_number",
                         format_spec="%s3" % padding_char,
                         strict_matching=False)

        # The padding char is missing in the format specifier, but we still need when validating
        # results.
        if padding_char == "":
            padding_char = " "

        # It should match because they are valid numbers.

        self.assertEqual(key.value_from_str("000"), 0)
        self.assertEqual(key.value_from_str("0"), 0)
        self.assertEqual(key.value_from_str("0"), 0)

        # While the number doesn't make any sense as far as formatting is concerned, this used
        # to work in old versions of Toolkit and needs to keep working in non strict mode.
        self.assertEqual(key.value_from_str("%s000" % padding_char), 0)

        # It should match a template with too many digits...
        self.assertEqual(key.value_from_str("20000"), 20000)

        # ... even if they are all zeros because lossy matching.
        self.assertEqual(key.value_from_str("00000"), 0)

        # From path to tokens back to path should be lossy.
        value = key.value_from_str("1")
        self.assertEqual("%s%s1" % (padding_char, padding_char),
                         key.str_from_value(value))

        self._test_nan(key, "expected an Integer")

    def _test_nan(self, key, error_msg):
        """
        Tests a key with against values that are not numbers.

        :param key: Key to test.
        :param error_msg: Text that partially matches the error message.
        """
        # Should fail because not a number
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("aaaa")
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("0a")
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("a0")
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("aa")

    def _test_strict_matching(self, padding_char):
        """
        Allows to test strict matching with any padding type.
        """
        # have a template that formats with two digits of padding.
        key = IntegerKey("version_number",
                         format_spec="%s3" % padding_char,
                         strict_matching=True)
        self.assertTrue(key.strict_matching)

        # The padding char is missing in the format specifier, but we still need when validating
        # results.
        if padding_char == "":
            padding_char = " "

        # From path to tokens back to path should get back the same string when the expected number of
        # digits are found.
        value = key.value_from_str("%s%s1" % (padding_char, padding_char))
        self.assertEqual("%s%s1" % (padding_char, padding_char),
                         key.str_from_value(value))

        # It should match a template with more digits.
        value = key.value_from_str("20000")
        self.assertEqual("20000", key.str_from_value(value))

        key.value_from_str("123")

        error_msg = "does not match format spec"

        # It should not match a string with too few digits
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("1")

        # It should not match a template with too many digits that are all zero because that would
        # lossy. (there are more zeros than the format spec can rebuild)
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("0000")

        # It should not match negative numbers either
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("-1000")

        # It should not match baddly padded numbers
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("0100")

        # It should not match negative values
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("-01")

        self._test_nan(key, error_msg)

    def test_strict_matching(self):
        """
        In strict mode, tokens have to have as much padding as the format specifier suggests. Less will not
        match.
        """
        self._test_strict_matching("")
        self._test_strict_matching("0")
    def _test_strict_matching(self, padding_char):
        """
        Allows to test strict matching with any padding type.
        """
        # have a template that formats with two digits of padding.
        key = IntegerKey("version_number", format_spec="%s3" % padding_char, strict_matching=True)
        self.assertTrue(key.strict_matching)

        # The padding char is missing in the format specifier, but we still need when validating
        # results.
        if padding_char == '':
            padding_char = ' '

        # From path to tokens back to path should get back the same string when the expected number of
        # digits are found.
        value = key.value_from_str("%s%s1" % (padding_char, padding_char))
        self.assertEqual("%s%s1" % (padding_char, padding_char), key.str_from_value(value))

        # It should match a template with more digits.
        value = key.value_from_str("20000")
        self.assertEqual("20000", key.str_from_value(value))

        key.value_from_str("123")

        error_msg = "does not match format spec"

        # It should not match a string with too few digits
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("1")

        # It should not match a template with too many digits that are all zero because that would
        # lossy. (there are more zeros than the format spec can rebuild)
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("0000")

        # It should not match negative numbers either
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("-1000")

        # It should not match baddly padded numbers
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("0100")

        # It should not match negative values
        with self.assertRaisesRegex(TankError, error_msg):
            key.value_from_str("-01")

        self._test_nan(key, error_msg)
Example #26
0
    def test_init_validation(self):
        """
        Makes sure that parameter validation is correct in the constructor.
        """
        # This should obviously work
        self._validate_key(IntegerKey("version_number"),
                           strict_matching=None,
                           format_spec=None)
        # When specifying parameters, they should be set accordingly.
        self._validate_key(
            IntegerKey("version_number",
                       format_spec="03",
                       strict_matching=True),
            strict_matching=True,
            format_spec="03",
        )
        self._validate_key(
            IntegerKey("version_number",
                       format_spec="03",
                       strict_matching=False),
            strict_matching=False,
            format_spec="03",
        )
        self._validate_key(
            IntegerKey("version_number",
                       format_spec="3",
                       strict_matching=False),
            strict_matching=False,
            format_spec="3",
        )
        # When specifying a format but not specifying the strict_matching, it should
        # still have strict_matching.
        self._validate_key(
            IntegerKey("version_number", format_spec="03"),
            strict_matching=True,
            format_spec="03",
        )
        # Make sure than an error is raised when wrong types are passed in.
        with self.assertRaisesRegex(TankError, "is not of type boolean"):
            IntegerKey("version_number", strict_matching=1)

        with self.assertRaisesRegex(TankError, "is not of type string"):
            IntegerKey("version_number", format_spec=1)

        # Make sure that if the user specifies strict_matching with no format
        # there is an error
        error_regexp = "strict_matching can't be set"
        with self.assertRaisesRegex(TankError, error_regexp):
            IntegerKey("version_number", strict_matching=False)

        with self.assertRaisesRegex(TankError, error_regexp):
            IntegerKey("version_number", strict_matching=True)

        # We support 4 format_spec values:
        # - None
        # - non zero positive number
        # - zero followed by a non zero positive number
        IntegerKey("version_number", format_spec=None)
        IntegerKey("version_number", format_spec="1")
        IntegerKey("version_number", format_spec="01")

        # Make sure invalid formats are caught
        with self.assertRaisesRegex(TankError, "format_spec can't be empty"):
            IntegerKey("version_number", format_spec="")

        error_regexp = "has to either be"
        # We don't support the sign option.
        with self.assertRaisesRegex(TankError, error_regexp):
            IntegerKey("version_number",
                       format_spec=" 3",
                       strict_matching=False)

        with self.assertRaisesRegex(TankError, error_regexp):
            # Should throw because the padding number is not non zero.
            IntegerKey("version_number", format_spec="00")

        with self.assertRaisesRegex(TankError, error_regexp):
            # Should throw because it is not a non zero positive integer
            IntegerKey("version_number", format_spec="0")

        with self.assertRaisesRegex(TankError, error_regexp):
            # Should throw because the padding caracter is invalid
            IntegerKey("version_number", format_spec="a0")

        with self.assertRaisesRegex(TankError, error_regexp):
            # Should throw because the padding size is not a number.
            IntegerKey("version_number", format_spec="0a")
Example #27
0
 def setUp(self):
     super(TestIntegerKey, self).setUp()
     self.int_field = IntegerKey("field_name")