1#!/pxrpythonsubst
2#
3# Copyright 2018 Pixar
4#
5# Licensed under the Apache License, Version 2.0 (the "Apache License")
6# with the following modification; you may not use this file except in
7# compliance with the Apache License and the following modification to it:
8# Section 6. Trademarks. is deleted and replaced with:
9#
10# 6. Trademarks. This License does not grant permission to use the trade
11#    names, trademarks, service marks, or product names of the Licensor
12#    and its affiliates, except as required to comply with Section 4(c) of
13#    the License and to reproduce the content of the NOTICE file.
14#
15# You may obtain a copy of the Apache License at
16#
17#     http://www.apache.org/licenses/LICENSE-2.0
18#
19# Unless required by applicable law or agreed to in writing, software
20# distributed under the Apache License with the above modification is
21# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
22# KIND, either express or implied. See the Apache License for the specific
23# language governing permissions and limitations under the Apache License.
24#
25
26from __future__ import print_function
27
28import argparse, sys, os
29
30from pxr import Ar
31
32def _HasCreateIdentifier():
33    return hasattr(Ar.Resolver, "CreateIdentifier")
34
35def _HasConfigureResolverForAsset():
36    return hasattr(Ar.Resolver, "ConfigureResolverForAsset")
37
38def _Msg(msg):
39    sys.stdout.write(msg + '\n')
40
41def _Err(msg):
42    sys.stderr.write(msg + '\n')
43
44def _ConfigureAssetResolver(args, resolver):
45    if _HasConfigureResolverForAsset():
46        configurePath = args.configureAssetPath or args.inputPath
47        resolver.ConfigureResolverForAsset(configurePath)
48    else:
49        if args.createContextForAsset:
50            return resolver.CreateDefaultContextForAsset(
51                args.createContextForAsset)
52        elif args.createContextFromString:
53            configStrs = []
54            for s in args.createContextFromString:
55                try:
56                    uriScheme, config = s.split(":", 1)
57                    configStrs.append((uriScheme, config))
58                except ValueError:
59                    configStrs.append(("", s))
60            return resolver.CreateContextFromStrings(configStrs)
61
62    return resolver.CreateDefaultContextForAsset(args.inputPath)
63
64def _AnchorRelativePath(args, resolver):
65    if args.anchorPath:
66        if _HasCreateIdentifier():
67            return resolver.CreateIdentifier(
68                args.inputPath, Ar.ResolvedPath(args.anchorPath))
69        elif resolver.IsRelativePath(args.inputPath):
70            return resolver.AnchorRelativePath(args.anchorPath, args.inputPath)
71    return args.inputPath
72
73
74def main():
75    parser = argparse.ArgumentParser(
76        description='Resolves an asset path using a fully configured USD Asset Resolver.')
77
78    parser.add_argument('inputPath',
79        help="An asset path to be resolved by the USD Asset Resolver.")
80
81    if _HasConfigureResolverForAsset():
82        parser.add_argument(
83            '--configureAssetPath',
84            help="Run ConfigureResolverForAsset on the given asset path.")
85    else:
86        subparser = parser.add_mutually_exclusive_group()
87        subparser.add_argument(
88            '--createContextForAsset',
89            help=("Run CreateDefaultContextForAsset with the given asset path "
90                  "to create the context used for resolution."))
91        subparser.add_argument(
92            '--createContextFromString', action='append',
93            help=("Run CreateContextFromString with the given string to create "
94                  "the context used for resolution. This accepts strings like "
95                  "[<URI Scheme>:]<Configuration String> and may be specified "
96                  "multiple times.\n\n"
97                  "ex: usdresolve --createContextFromString 'config_primary' "
98                  "--createContextFromString 'my_uri_scheme:config_uri'"))
99
100    if _HasCreateIdentifier():
101        parser.add_argument(
102            '--anchorPath',
103            help=("Run CreateIdentifier with the input path and this anchor "
104                  "asset path and resolve the result.\n\n"
105                  "ex: usdresolve --anchorPath /asset/asset.usd sublayer.usd"))
106    else:
107        parser.add_argument(
108            '--anchorPath',
109            help="Run AnchorRelativePath on the given asset path.")
110
111
112    args = parser.parse_args()
113
114    exitCode = 0
115
116    resolver = Ar.GetResolver()
117
118    try:
119        resolverContext = _ConfigureAssetResolver(args, resolver)
120        with Ar.ResolverContextBinder(resolverContext):
121            inputPath = _AnchorRelativePath(args, resolver)
122            resolved = resolver.Resolve(inputPath)
123    except Exception as e:
124        _Err("Failed to resolve '%s' - %s" % (args.inputPath, e))
125        exitCode = 1
126
127    if not resolved:
128        _Err("Failed to resolve '%s'" % args.inputPath)
129        exitCode = 1
130    else:
131        print(resolved)
132
133    return exitCode
134
135if __name__ == "__main__":
136    # Restore signal handling defaults to allow output redirection and the like.
137    import platform
138    if platform.system() != 'Windows':
139        import signal
140        signal.signal(signal.SIGPIPE, signal.SIG_DFL)
141    sys.exit(main())
142