text: //
  // Copyright 2016 Pixar
  //
  // Licensed under the Apache License, Version 2.0 (the "Apache License")
  // with the following modification; you may not use this file except in
  // compliance with the Apache License and the following modification to it:
  // Section 6. Trademarks. is deleted and replaced with:
  //
  // 6. Trademarks. This License does not grant permission to use the trade
  //    names, trademarks, service marks, or product names of the Licensor
  //    and its affiliates, except as required to comply with Section 4(c) of
  //    the License and to reproduce the content of the NOTICE file.
  //
  // You may obtain a copy of the Apache License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the Apache License with the above modification is
  // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  // KIND, either express or implied. See the Apache License for the specific
  // language governing permissions and limitations under the Apache License.
  //
  #include "pxr/pxr.h"
  #include "pxr/usd/usd/object.h"
  
  #include "pxr/usd/usd/prim.h"
  #include "pxr/usd/usd/wrapUtils.h"
  
  #include "pxr/base/tf/ostreamMethods.h"
  
  #include "pxr/usd/usd/pyConversions.h"
  #include "pxr/base/tf/pyContainerConversions.h"
  #include "pxr/base/tf/pyResultConversions.h"
  #include "pxr/base/tf/pyUtils.h"
  
  #include <boost/python/class.hpp>
  #include <boost/python/operators.hpp>
  #include <boost/python/extract.hpp>
  
  #include <string>
  #include <vector>
  
  using std::string;
  using std::vector;
  
  using namespace boost::python;
  
  PXR_NAMESPACE_USING_DIRECTIVE
  
  namespace {
  
  static TfPyObjWrapper
  _GetMetadata(const UsdObject &self, const TfToken &key)
  {
      VtValue result;
      self.GetMetadata(key, &result);
      return UsdVtValueToPython(result);
  }
  
  static TfPyObjWrapper
  _GetMetadataByDictKey(
      const UsdObject &self, const TfToken &key, const TfToken &keyPath)
  {
      VtValue result;
      self.GetMetadataByDictKey(key, keyPath, &result);
      return UsdVtValueToPython(result);
  }
  
  
  static bool _SetMetadata(const UsdObject &self, const TfToken& key,
                           object obj) {
      VtValue value;
      return UsdPythonToMetadataValue(key, /*keyPath*/TfToken(), obj, &value) &&
          self.SetMetadata(key, value);
  }
  
  static bool _SetMetadataByDictKey(const UsdObject &self, const TfToken& key,
                                    const TfToken &keyPath, object obj) {
      VtValue value;
      return UsdPythonToMetadataValue(key, keyPath, obj, &value) &&
          self.SetMetadataByDictKey(key, keyPath, value);
  }
  
  static TfPyObjWrapper _GetCustomData(const UsdObject &self) {
      return UsdVtValueToPython(VtValue(self.GetCustomData()));
  }
  
  static TfPyObjWrapper _GetCustomDataByKey(
      const UsdObject &self, const TfToken &keyPath) {
      return UsdVtValueToPython(VtValue(self.GetCustomDataByKey(keyPath)));
  }
  
  static void _SetCustomData(UsdObject &self, object obj) {
      VtValue value;
      if (UsdPythonToMetadataValue(
              SdfFieldKeys->CustomData, TfToken(), obj, &value) &&
          value.IsHolding<VtDictionary>()) {
          self.SetCustomData(value.UncheckedGet<VtDictionary>());
      }
  }
  
  static void _SetCustomDataByKey(
      UsdObject &self, const TfToken &keyPath, object obj) {
      VtValue value;
      if (UsdPythonToMetadataValue(
              SdfFieldKeys->CustomData, keyPath, obj, &value)) {
          self.SetCustomDataByKey(keyPath, value);
      }
  }
  
  static TfPyObjWrapper _GetAssetInfo(const UsdObject &self) {
      return UsdVtValueToPython(VtValue(self.GetAssetInfo()));
  }
  
  static TfPyObjWrapper _GetAssetInfoByKey(
      const UsdObject &self, const TfToken &keyPath) {
      return UsdVtValueToPython(VtValue(self.GetAssetInfoByKey(keyPath)));
  }
  
  static void _SetAssetInfo(UsdObject &self, object obj) {
      VtValue value;
      if (UsdPythonToMetadataValue(
              SdfFieldKeys->AssetInfo, TfToken(), obj, &value) &&
          value.IsHolding<VtDictionary>()) {
          self.SetAssetInfo(value.UncheckedGet<VtDictionary>());
      }
  }
  
  static void _SetAssetInfoByKey(
      UsdObject &self, const TfToken &keyPath, object obj) {
      VtValue value;
      if (UsdPythonToMetadataValue(
              SdfFieldKeys->AssetInfo, keyPath, obj, &value)) {
          self.SetAssetInfoByKey(keyPath, value);
      }
  }
  
  static size_t __hash__(const UsdObject &self) { return hash_value(self); }
  
  // We override __getattribute__ for UsdObject to check object validity and raise
  // an exception instead of crashing from Python.
  
  // Store the original __getattribute__ so we can dispatch to it after verifying
  // validity.
  static TfStaticData<TfPyObjWrapper> _object__getattribute__;
  
  // This function gets wrapped as __getattribute__ on UsdObject.
  static object
  __getattribute__(object selfObj, const char *name) {
      // Allow attribute lookups if the attribute name starts with '__', if the
      // object's prim is valid, or if the attribute is one of a specific
      // whitelist.
      if ((name[0] == '_' && name[1] == '_') ||
          extract<UsdObject &>(selfObj)().GetPrim().IsValid() ||
          strcmp(name, "IsValid") == 0 ||
          strcmp(name, "IsDefined") == 0 ||
          strcmp(name, "GetDescription") == 0 ||
          strcmp(name, "GetPrim") == 0 ||
          strcmp(name, "GetPath") == 0 ||
          strcmp(name, "GetPrimPath") == 0) {
          // Dispatch to object's __getattribute__.
          return (*_object__getattribute__)(selfObj, name);
      } else {
          // Otherwise raise a runtime error.
          TfPyThrowRuntimeError(
              TfStringPrintf("Accessed %s", TfPyRepr(selfObj).c_str()));
      }
      // Unreachable.
      return object();
  }
  
  } // anonymous namespace 
  
  void wrapUsdObject()
  {
      class_<UsdObject> clsObj("Object");
      clsObj
          .def(Usd_ObjectSubclass())
          .def("IsValid", &UsdObject::IsValid)
  
          .def(self == self)
          .def(self != self)
          .def(!self)
          .def("__hash__", __hash__)
  
          .def("GetStage", &UsdObject::GetStage)
          .def("GetPath", &UsdObject::GetPath)
          .def("GetPrimPath", &UsdObject::GetPrimPath,
               return_value_policy<return_by_value>())
          .def("GetPrim", &UsdObject::GetPrim)
          .def("GetName", &UsdObject::GetName,
               return_value_policy<return_by_value>())
          .def("GetDescription", &UsdObject::GetDescription)
  
          .def("GetMetadata", _GetMetadata, arg("key"))
          .def("SetMetadata", _SetMetadata, (arg("key"), arg("value")))
  
          .def("ClearMetadata", &UsdObject::ClearMetadata, arg("key"))
          .def("HasMetadata", &UsdObject::HasMetadata, arg("key"))
          .def("HasAuthoredMetadata", &UsdObject::HasAuthoredMetadata, arg("key"))
  
          .def("GetMetadataByDictKey", _GetMetadataByDictKey,
               (arg("key"), arg("keyPath")))
          .def("SetMetadataByDictKey", _SetMetadataByDictKey,
               (arg("key"), arg("keyPath"), arg("value")))
  
          .def("ClearMetadataByDictKey", &UsdObject::ClearMetadataByDictKey,
               (arg("key"), arg("keyPath")))
          .def("HasMetadataDictKey", &UsdObject::HasMetadataDictKey,
               (arg("key"), arg("keyPath")))
          .def("HasAuthoredMetadataDictKey",
               &UsdObject::HasAuthoredMetadataDictKey,
               (arg("key"), arg("keyPath")))
  
          .def("GetAllMetadata", &UsdObject::GetAllMetadata,
               return_value_policy<TfPyMapToDictionary>())
          .def("GetAllAuthoredMetadata", &UsdObject::GetAllAuthoredMetadata,
               return_value_policy<TfPyMapToDictionary>())
  
          .def("IsHidden", &UsdObject::IsHidden)
          .def("SetHidden", &UsdObject::SetHidden, arg("hidden"))
          .def("ClearHidden", &UsdObject::ClearHidden)
          .def("HasAuthoredHidden", &UsdObject::HasAuthoredHidden)
  
          .def("GetCustomData", _GetCustomData)
          .def("GetCustomDataByKey", _GetCustomDataByKey,
               arg("keyPath"))
          .def("SetCustomData", _SetCustomData, arg("customData"))
          .def("SetCustomDataByKey", _SetCustomDataByKey,
               (arg("keyPath"), arg("value")))
          .def("ClearCustomData", &UsdObject::ClearCustomData)
          .def("ClearCustomDataByKey", &UsdObject::ClearCustomDataByKey,
               arg("keyPath"))
  
          .def("HasCustomData", &UsdObject::HasCustomData)
          .def("HasCustomDataKey", &UsdObject::HasCustomDataKey, arg("keyPath"))
          .def("HasAuthoredCustomData", &UsdObject::HasAuthoredCustomData)
          .def("HasAuthoredCustomDataKey", &UsdObject::HasAuthoredCustomDataKey,
               arg("keyPath"))
  
          .def("GetAssetInfo", _GetAssetInfo)
          .def("GetAssetInfoByKey", _GetAssetInfoByKey,
               arg("keyPath"))
          .def("SetAssetInfo", _SetAssetInfo, arg("assetInfo"))
          .def("SetAssetInfoByKey", _SetAssetInfoByKey,
               (arg("keyPath"), arg("value")))
          .def("ClearAssetInfo", &UsdObject::ClearAssetInfo)
          .def("ClearAssetInfoByKey", &UsdObject::ClearAssetInfoByKey,
               arg("keyPath"))
  
          .def("HasAssetInfo", &UsdObject::HasAssetInfo)
          .def("HasAssetInfoKey", &UsdObject::HasAssetInfoKey, arg("keyPath"))
          .def("HasAuthoredAssetInfo", &UsdObject::HasAuthoredAssetInfo)
          .def("HasAuthoredAssetInfoKey", &UsdObject::HasAuthoredAssetInfoKey,
               arg("keyPath"))
          
          .def("GetDocumentation", &UsdObject::GetDocumentation)
          .def("SetDocumentation", &UsdObject::SetDocumentation, arg("doc"))
          .def("ClearDocumentation", &UsdObject::ClearDocumentation)
          .def("HasAuthoredDocumentation", &UsdObject::HasAuthoredDocumentation)
  
          .def("GetNamespaceDelimiter", &UsdObject::GetNamespaceDelimiter)
          .staticmethod("GetNamespaceDelimiter")
  
          ;
  
      // Save existing __getattribute__ and replace.
      *_object__getattribute__ = object(clsObj.attr("__getattribute__"));
      clsObj.def("__getattribute__", __getattribute__);
  
      TfPyRegisterStlSequencesFromPython<UsdObject>();
  }
  