1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24
25 #include "pxr/pxr.h"
26
27 #include "pxr/base/tf/pyArg.h"
28 #include "pxr/base/tf/pyUtils.h"
29 #include "pxr/base/tf/stringUtils.h"
30
31 #include <boost/python/extract.hpp>
32 #include <boost/python/list.hpp>
33 #include <boost/python/slice.hpp>
34 #include <boost/python/stl_iterator.hpp>
35
36 using std::string;
37 using std::vector;
38
39 using namespace boost::python;
40
41 PXR_NAMESPACE_OPEN_SCOPE
42
43 static bool
_ArgumentIsNamed(const std::string & name,const TfPyArg & arg)44 _ArgumentIsNamed(const std::string& name, const TfPyArg& arg)
45 {
46 return arg.GetName() == name;
47 }
48
49 std::pair<tuple, dict>
TfPyProcessOptionalArgs(const tuple & args,const dict & kwargs,const TfPyArgs & expectedArgs,bool allowExtraArgs)50 TfPyProcessOptionalArgs(
51 const tuple& args, const dict& kwargs,
52 const TfPyArgs& expectedArgs,
53 bool allowExtraArgs)
54 {
55 std::pair<tuple, dict> rval;
56
57 const unsigned int numArgs = static_cast<unsigned int>(len(args));
58 const unsigned int numExpectedArgs = static_cast<unsigned int>(expectedArgs.size());
59
60 if (!allowExtraArgs) {
61 if (numArgs > numExpectedArgs) {
62 TfPyThrowTypeError("Too many arguments for function");
63 }
64
65 const list keys = kwargs.keys();
66
67 typedef stl_input_iterator<string> KeyIterator;
68 for (KeyIterator it(keys), it_end; it != it_end; ++it) {
69 if (std::find_if(expectedArgs.begin(), expectedArgs.end(),
70 std::bind(_ArgumentIsNamed, *it,
71 std::placeholders::_1))
72 == expectedArgs.end()) {
73
74 TfPyThrowTypeError("Unexpected keyword argument '%s'");
75 }
76 }
77 }
78
79 rval.second = kwargs;
80
81 for (unsigned int i = 0; i < std::min(numArgs, numExpectedArgs); ++i) {
82 const string& argName = expectedArgs[i].GetName();
83 if (rval.second.has_key(argName)) {
84 TfPyThrowTypeError(
85 TfStringPrintf("Multiple values for keyword argument '%s'",
86 argName.c_str()));
87 }
88
89 rval.second[argName] = args[i];
90 }
91
92 if (numArgs > numExpectedArgs) {
93 rval.first = tuple(args[slice(numExpectedArgs, numArgs)]);
94 }
95
96 return rval;
97 }
98
99 static void
_AddArgAndTypeDocStrings(const TfPyArg & arg,vector<string> * argStrs,vector<string> * typeStrs)100 _AddArgAndTypeDocStrings(
101 const TfPyArg& arg, vector<string>* argStrs, vector<string>* typeStrs)
102 {
103 argStrs->push_back(arg.GetName());
104 if (!arg.GetDefaultValueDoc().empty()) {
105 argStrs->back() +=
106 TfStringPrintf(" = %s", arg.GetDefaultValueDoc().c_str());
107 }
108
109 typeStrs->push_back(
110 TfStringPrintf("%s : %s",
111 arg.GetName().c_str(), arg.GetTypeDoc().c_str()));
112 }
113
114 string
TfPyCreateFunctionDocString(const string & functionName,const TfPyArgs & requiredArgs,const TfPyArgs & optionalArgs,const string & description)115 TfPyCreateFunctionDocString(
116 const string& functionName,
117 const TfPyArgs& requiredArgs,
118 const TfPyArgs& optionalArgs,
119 const string& description)
120 {
121 string rval = functionName + "(";
122
123 vector<string> argStrs;
124 vector<string> typeStrs;
125
126 for (size_t i = 0; i < requiredArgs.size(); ++i) {
127 _AddArgAndTypeDocStrings(requiredArgs[i], &argStrs, &typeStrs);
128 }
129
130 for (size_t i = 0; i < optionalArgs.size(); ++i) {
131 _AddArgAndTypeDocStrings(optionalArgs[i], &argStrs, &typeStrs);
132 }
133
134 rval += TfStringJoin(argStrs.begin(), argStrs.end(), ", ");
135 rval += ")";
136
137 if (!typeStrs.empty()) {
138 rval += "\n";
139 rval += TfStringJoin(typeStrs.begin(), typeStrs.end(), "\n");
140 }
141
142 if (!description.empty()) {
143 rval += "\n\n";
144 rval += description;
145 }
146
147 return rval;
148 }
149
150 PXR_NAMESPACE_CLOSE_SCOPE
151