From c7a5a9b532f64a0c76175a8955de7ea725e9d312 Mon Sep 17 00:00:00 2001 From: Austin Henriksen Date: Mon, 10 Feb 2025 13:54:01 -0500 Subject: [PATCH] Python Metadata Validation (#3502) --- cpp/src/Slice/Parser.cpp | 7 + cpp/src/Slice/Parser.h | 1 + cpp/src/ice2slice/Gen.cpp | 6 +- cpp/src/slice2cpp/Gen.cpp | 8 +- cpp/src/slice2cs/CsUtil.cpp | 8 +- cpp/src/slice2cs/Gen.cpp | 4 +- cpp/src/slice2java/Gen.cpp | 2 +- cpp/src/slice2java/JavaUtil.cpp | 8 +- cpp/src/slice2js/Gen.cpp | 3 +- cpp/src/slice2py/PythonUtil.cpp | 327 +++++------------- cpp/src/slice2py/PythonUtil.h | 2 + cpp/src/slice2rb/RubyUtil.cpp | 2 +- cpp/src/slice2swift/Gen.cpp | 4 +- cpp/src/slice2swift/SwiftUtil.cpp | 6 +- python/modules/IcePy/msbuild/icepy.vcxproj | 1 + .../IcePy/msbuild/icepy.vcxproj.filters | 3 + python/test/Ice/custom/Test.ice | 10 +- 17 files changed, 123 insertions(+), 279 deletions(-) diff --git a/cpp/src/Slice/Parser.cpp b/cpp/src/Slice/Parser.cpp index 009e1e8504e..cd98a1060eb 100644 --- a/cpp/src/Slice/Parser.cpp +++ b/cpp/src/Slice/Parser.cpp @@ -91,6 +91,7 @@ namespace Slice // ---------------------------------------------------------------------- // Metadata // ---------------------------------------------------------------------- + Slice::Metadata::Metadata(string rawMetadata, string file, int line) { _file = std::move(file); @@ -874,6 +875,12 @@ Slice::Contained::container() const return _container; } +bool +Slice::Contained::isTopLevel() const +{ + return dynamic_pointer_cast(container()) != nullptr; +} + string Slice::Contained::name() const { diff --git a/cpp/src/Slice/Parser.h b/cpp/src/Slice/Parser.h index 174130e7b55..c71a6e1868a 100644 --- a/cpp/src/Slice/Parser.h +++ b/cpp/src/Slice/Parser.h @@ -381,6 +381,7 @@ namespace Slice public: virtual void destroy() {} [[nodiscard]] ContainerPtr container() const; + [[nodiscard]] bool isTopLevel() const; /// Returns the Slice identifier of this element. [[nodiscard]] std::string name() const; diff --git a/cpp/src/ice2slice/Gen.cpp b/cpp/src/ice2slice/Gen.cpp index 9bcf67243d2..0c5c0aef2a4 100644 --- a/cpp/src/ice2slice/Gen.cpp +++ b/cpp/src/ice2slice/Gen.cpp @@ -87,12 +87,12 @@ namespace } } - ContainerPtr c = p->container(); - p = dynamic_pointer_cast(c); // This cast fails for Unit. - if (!p) + if (p->isTopLevel()) { break; } + p = dynamic_pointer_cast(p->container()); + assert(p); } assert(m); diff --git a/cpp/src/slice2cpp/Gen.cpp b/cpp/src/slice2cpp/Gen.cpp index e8b384d9213..899c060c523 100644 --- a/cpp/src/slice2cpp/Gen.cpp +++ b/cpp/src/slice2cpp/Gen.cpp @@ -3254,11 +3254,9 @@ Slice::Gen::StreamVisitor::visitModuleStart(const ModulePtr& m) return false; } - if (dynamic_pointer_cast(m->container())) + if (m->isTopLevel()) { - // // Only emit this for the top-level module. - // H << sp; H << nl << "/// \\cond STREAM"; H << nl << "namespace Ice" << nl << '{'; @@ -3270,11 +3268,9 @@ Slice::Gen::StreamVisitor::visitModuleStart(const ModulePtr& m) void Slice::Gen::StreamVisitor::visitModuleEnd(const ModulePtr& m) { - if (dynamic_pointer_cast(m->container())) + if (m->isTopLevel()) { - // // Only emit this for the top-level module. - // H.dec(); H << nl << '}'; H << nl << "/// \\endcond"; diff --git a/cpp/src/slice2cs/CsUtil.cpp b/cpp/src/slice2cs/CsUtil.cpp index dcacbabc001..190c829223a 100644 --- a/cpp/src/slice2cs/CsUtil.cpp +++ b/cpp/src/slice2cs/CsUtil.cpp @@ -36,12 +36,12 @@ Slice::CsGenerator::getNamespacePrefix(const ContainedPtr& cont) m = dynamic_pointer_cast(p); } - ContainerPtr c = p->container(); - p = dynamic_pointer_cast(c); // This cast fails for Unit. - if (!p) + if (p->isTopLevel()) { break; } + p = dynamic_pointer_cast(p->container()); + assert(p); } assert(m); @@ -1849,7 +1849,7 @@ Slice::CsGenerator::validateMetadata(const UnitPtr& u) { // 'cs:namespace' can only be applied to top-level modules // Top-level modules are contained by the 'Unit'. Non-top-level modules are contained in 'Module's. - if (auto mod = dynamic_pointer_cast(p); mod && !dynamic_pointer_cast(mod->container())) + if (auto mod = dynamic_pointer_cast(p); mod && !mod->isTopLevel()) { return "the 'cs:namespace' metadata can only be applied to top-level modules"; } diff --git a/cpp/src/slice2cs/Gen.cpp b/cpp/src/slice2cs/Gen.cpp index 50c79364b89..ebf632119d8 100644 --- a/cpp/src/slice2cs/Gen.cpp +++ b/cpp/src/slice2cs/Gen.cpp @@ -753,7 +753,7 @@ Slice::CsVisitor::writeParameterDocComments(const DocComment& comment, const Par void Slice::CsVisitor::moduleStart(const ModulePtr& p) { - if (!dynamic_pointer_cast(p->container())) + if (p->isTopLevel()) { string ns = getNamespacePrefix(p); if (!ns.empty()) @@ -768,7 +768,7 @@ Slice::CsVisitor::moduleStart(const ModulePtr& p) void Slice::CsVisitor::moduleEnd(const ModulePtr& p) { - if (!dynamic_pointer_cast(p->container())) + if (p->isTopLevel()) { if (!getNamespacePrefix(p).empty()) { diff --git a/cpp/src/slice2java/Gen.cpp b/cpp/src/slice2java/Gen.cpp index fb488687f91..84665999aae 100644 --- a/cpp/src/slice2java/Gen.cpp +++ b/cpp/src/slice2java/Gen.cpp @@ -2241,7 +2241,7 @@ bool Slice::Gen::TypesVisitor::visitModuleStart(const ModulePtr& p) { string prefix = getPackagePrefix(p); - if (!prefix.empty() && dynamic_pointer_cast(p->container())) // generate Marker class for top-level modules + if (!prefix.empty() && p->isTopLevel()) // generate Marker class for top-level modules { string markerClass = prefix + "." + fixKwd(p->name()) + "._Marker"; open(markerClass, p->file()); diff --git a/cpp/src/slice2java/JavaUtil.cpp b/cpp/src/slice2java/JavaUtil.cpp index 80272e0c909..4779b8f9e97 100644 --- a/cpp/src/slice2java/JavaUtil.cpp +++ b/cpp/src/slice2java/JavaUtil.cpp @@ -435,12 +435,12 @@ Slice::JavaGenerator::getPackagePrefix(const ContainedPtr& cont) m = dynamic_pointer_cast(p); } - ContainerPtr c = p->container(); - p = dynamic_pointer_cast(c); // This cast fails for Unit. - if (!p) + if (p->isTopLevel()) { break; } + p = dynamic_pointer_cast(p->container()); + assert(p); } assert(m); @@ -1839,7 +1839,7 @@ Slice::JavaGenerator::validateMetadata(const UnitPtr& u) { // If 'java:package' is applied to a module, it must be a top-level module. // // Top-level modules are contained by the 'Unit'. Non-top-level modules are contained in 'Module's. - if (auto mod = dynamic_pointer_cast(p); mod && !dynamic_pointer_cast(mod->container())) + if (auto mod = dynamic_pointer_cast(p); mod && !mod->isTopLevel()) { return "the 'java:package' metadata can only be applied at the file level or to top-level modules"; } diff --git a/cpp/src/slice2js/Gen.cpp b/cpp/src/slice2js/Gen.cpp index a9c32e5023b..fbe54494f95 100644 --- a/cpp/src/slice2js/Gen.cpp +++ b/cpp/src/slice2js/Gen.cpp @@ -1041,10 +1041,9 @@ Slice::Gen::ExportsVisitor::visitModuleStart(const ModulePtr& p) const string scoped = getLocalScope(p->scoped()); if (_exportedModules.insert(scoped).second) { - const bool topLevel = dynamic_pointer_cast(p->container()) != nullptr; _out << sp; _out << nl; - if (topLevel) + if (p->isTopLevel()) { if (_importedModules.find(scoped) == _importedModules.end()) { diff --git a/cpp/src/slice2py/PythonUtil.cpp b/cpp/src/slice2py/PythonUtil.cpp index 2aedd203dbe..83156e00175 100644 --- a/cpp/src/slice2py/PythonUtil.cpp +++ b/cpp/src/slice2py/PythonUtil.cpp @@ -1,6 +1,7 @@ // Copyright (c) ZeroC, Inc. #include "PythonUtil.h" +#include "../Slice/MetadataValidation.h" #include "../Slice/Util.h" #include "Ice/StringUtil.h" @@ -153,30 +154,6 @@ namespace namespace Slice::Python { - class MetadataVisitor final : public ParserVisitor - { - public: - bool visitUnitStart(const UnitPtr&) final; - bool visitModuleStart(const ModulePtr&) final; - void visitClassDecl(const ClassDeclPtr&) final; - void visitInterfaceDecl(const InterfaceDeclPtr&) final; - bool visitExceptionStart(const ExceptionPtr&) final; - bool visitStructStart(const StructPtr&) final; - void visitOperation(const OperationPtr&) final; - void visitDataMember(const DataMemberPtr&) final; - void visitSequence(const SequencePtr&) final; - void visitDictionary(const DictionaryPtr&) final; - void visitEnum(const EnumPtr&) final; - void visitConst(const ConstPtr&) final; - - private: - /// Validates sequence metadata. - MetadataList validateSequence(const ContainedPtr&, const TypePtr&); - - /// Checks a definition that doesn't currently support Python metadata. - void reject(const ContainedPtr&); - }; - // // ModuleVisitor finds all of the Slice modules whose include level is greater // than 0 and emits a statement of the following form: @@ -352,12 +329,10 @@ Slice::Python::ModuleVisitor::visitModuleStart(const ModulePtr& p) string abs = getAbsolute(p); if (_history.count(abs) == 0) { - // // If this is a top-level module, then we check if it has package metadata. // If so, we need to emit statements to open each of the modules in the // package before we can open this module. - // - if (dynamic_pointer_cast(p->container())) + if (p->isTopLevel()) { string pkg = getPackageMetadata(p); if (!pkg.empty()) @@ -414,12 +389,10 @@ Slice::Python::CodeVisitor::visitModuleStart(const ModulePtr& p) _out << sp << nl << "# Start of module " << abs; if (_moduleHistory.count(abs) == 0) // Don't emit this more than once for each module. { - // // If this is a top-level module, then we check if it has package metadata. // If so, we need to emit statements to open each of the modules in the // package before we can open this module. - // - if (dynamic_pointer_cast(p->container())) + if (p->isTopLevel()) { string pkg = getPackageMetadata(p); if (!pkg.empty()) @@ -2424,10 +2397,9 @@ Slice::Python::getImportFileName(const string& file, const UnitPtr& ut, const ve } void -Slice::Python::generate(const UnitPtr& un, bool all, const vector& includePaths, Output& out) +Slice::Python::generate(const UnitPtr& unit, bool all, const vector& includePaths, Output& out) { - Slice::Python::MetadataVisitor visitor; - un->visit(&visitor); + validateMetadata(unit); out << nl << "import Ice"; out << nl << "import IcePy"; @@ -2441,20 +2413,20 @@ Slice::Python::generate(const UnitPtr& un, bool all, const vector& inclu path = fullPath(path); } - StringList includes = un->includeFiles(); + StringList includes = unit->includeFiles(); for (const auto& include : includes) { - out << nl << "import " << getImportFileName(include, un, paths); + out << nl << "import " << getImportFileName(include, unit, paths); } } set moduleHistory; ModuleVisitor moduleVisitor(out, moduleHistory); - un->visit(&moduleVisitor); + unit->visit(&moduleVisitor); CodeVisitor codeVisitor(out, moduleHistory); - un->visit(&codeVisitor); + unit->visit(&codeVisitor); out << nl; // Trailing newline. } @@ -2509,12 +2481,12 @@ Slice::Python::getPackageMetadata(const ContainedPtr& cont) m = dynamic_pointer_cast(p); } - ContainerPtr c = p->container(); - p = dynamic_pointer_cast(c); // This cast fails for Unit. - if (!p) + if (p->isTopLevel()) { break; } + p = dynamic_pointer_cast(p->container()); + assert(p); } assert(m); @@ -2563,223 +2535,88 @@ Slice::Python::printHeader(IceInternal::Output& out) out << "#\n"; } -bool -Slice::Python::MetadataVisitor::visitUnitStart(const UnitPtr& unit) -{ - // Validate file metadata in the top-level file and all included files. - for (const auto& file : unit->allFiles()) - { - DefinitionContextPtr dc = unit->findDefinitionContext(file); - MetadataList fileMetadata = dc->getMetadata(); - for (auto r = fileMetadata.begin(); r != fileMetadata.end();) - { - MetadataPtr meta = *r++; - string_view directive = meta->directive(); - string_view arguments = meta->arguments(); - - if (directive.find("python:") == 0) - { - if (directive == "python:package" && !arguments.empty()) - { - continue; - } - if (directive == "python:pkgdir" && !arguments.empty()) - { - continue; - } - - ostringstream msg; - msg << "ignoring invalid file metadata '" << *meta << "'"; - unit->warning(meta->file(), meta->line(), InvalidMetadata, msg.str()); - fileMetadata.remove(meta); - } - } - dc->setMetadata(fileMetadata); - } - return true; -} - -bool -Slice::Python::MetadataVisitor::visitModuleStart(const ModulePtr& p) +void +Slice::Python::validateMetadata(const UnitPtr& unit) { - MetadataList metadata = p->getMetadata(); - for (auto r = metadata.begin(); r != metadata.end();) + auto pythonArrayTypeValidationFunc = [](const MetadataPtr& m, const SyntaxTreeBasePtr& p) -> optional { - MetadataPtr meta = *r++; - string_view directive = meta->directive(); - - if (directive.find("python:") == 0) + if (auto sequence = dynamic_pointer_cast(p)) { - // Must be a top-level module. - if (dynamic_pointer_cast(p->container()) && directive == "python:package") + BuiltinPtr builtin = dynamic_pointer_cast(sequence->type()); + if (!builtin || !(builtin->isNumericType() || builtin->kind() == Builtin::KindBool)) { - continue; + return "the '" + m->directive() + + "' metadata can only be applied to sequences of bools, bytes, shorts, ints, longs, floats, " + "or doubles"; } - - ostringstream msg; - msg << "ignoring invalid file metadata '" << *meta << "'"; - p->unit()->warning(meta->file(), meta->line(), InvalidMetadata, msg.str()); - metadata.remove(meta); } - } - - p->setMetadata(std::move(metadata)); - return true; -} - -void -Slice::Python::MetadataVisitor::visitClassDecl(const ClassDeclPtr& p) -{ - reject(p); -} - -void -Slice::Python::MetadataVisitor::visitInterfaceDecl(const InterfaceDeclPtr& p) -{ - reject(p); -} - -bool -Slice::Python::MetadataVisitor::visitExceptionStart(const ExceptionPtr& p) -{ - reject(p); - return true; -} - -bool -Slice::Python::MetadataVisitor::visitStructStart(const StructPtr& p) -{ - reject(p); - return true; -} - -void -Slice::Python::MetadataVisitor::visitOperation(const OperationPtr& p) -{ - TypePtr ret = p->returnType(); - if (ret) - { - validateSequence(p, ret); - } - - for (const auto& param : p->parameters()) - { - validateSequence(param, param->type()); - } -} - -void -Slice::Python::MetadataVisitor::visitDataMember(const DataMemberPtr& p) -{ - validateSequence(p, p->type()); -} - -void -Slice::Python::MetadataVisitor::visitSequence(const SequencePtr& p) -{ - p->setMetadata(validateSequence(p, p)); -} - -void -Slice::Python::MetadataVisitor::visitDictionary(const DictionaryPtr& p) -{ - reject(p); -} - -void -Slice::Python::MetadataVisitor::visitEnum(const EnumPtr& p) -{ - reject(p); -} + return nullopt; + }; -void -Slice::Python::MetadataVisitor::visitConst(const ConstPtr& p) -{ - reject(p); -} + map knownMetadata; -MetadataList -Slice::Python::MetadataVisitor::validateSequence(const ContainedPtr& cont, const TypePtr& type) -{ - static const string prefix = "python:"; - MetadataList newMetadata = cont->getMetadata(); - for (auto p = newMetadata.begin(); p != newMetadata.end();) - { - MetadataPtr s = *p++; - string_view directive = s->directive(); - string_view arguments = s->arguments(); + // "python:" + MetadataInfo arrayTypeInfo = { + .validOn = {typeid(Sequence)}, + .acceptedArgumentKind = MetadataArgumentKind::NoArguments, + .acceptedContext = MetadataApplicationContext::DefinitionsAndTypeReferences, + .extraValidation = pythonArrayTypeValidationFunc, + }; + knownMetadata.emplace("python:array.array", arrayTypeInfo); + knownMetadata.emplace("python:numpy.ndarray", std::move(arrayTypeInfo)); + + // "python:memoryview" + MetadataInfo memoryViewInfo = { + .validOn = {typeid(Sequence)}, + .acceptedArgumentKind = MetadataArgumentKind::RequiredTextArgument, + .acceptedContext = MetadataApplicationContext::DefinitionsAndTypeReferences, + .extraValidation = pythonArrayTypeValidationFunc, + }; + knownMetadata.emplace("python:memoryview", std::move(memoryViewInfo)); - if (directive.find(prefix) == 0) + // "python:package" + MetadataInfo packageInfo = { + .validOn = {typeid(Module), typeid(Unit)}, + .acceptedArgumentKind = MetadataArgumentKind::SingleArgument, + .extraValidation = [](const MetadataPtr&, const SyntaxTreeBasePtr& p) -> optional { - SequencePtr seq = dynamic_pointer_cast(type); - if (seq) + // If 'python:package' is applied to a module, it must be a top-level module. + // Top-level modules are contained by the 'Unit'. Non-top-level modules are contained in 'Module's. + if (auto mod = dynamic_pointer_cast(p); mod && !mod->isTopLevel()) { - if (directive == "python:seq") - { - if (arguments == "tuple" || arguments == "list" || arguments == "default") - { - continue; - } - } - else if (directive.size() > prefix.size()) - { - string_view subArg = directive.substr(prefix.size()); - if (subArg == "tuple" || subArg == "list" || subArg == "default") - { - continue; - } - else if (subArg == "array.array" || subArg == "numpy.ndarray" || subArg.find("memoryview") == 0) - { - // The memoryview sequence metadata is only valid for integral builtin - // types excluding strings. - BuiltinPtr builtin = dynamic_pointer_cast(seq->type()); - if (builtin) - { - switch (builtin->kind()) - { - case Builtin::KindBool: - case Builtin::KindByte: - case Builtin::KindShort: - case Builtin::KindInt: - case Builtin::KindLong: - case Builtin::KindFloat: - case Builtin::KindDouble: - { - continue; - } - default: - { - break; - } - } - } - } - } + return "the 'python:package' metadata can only be applied at the file level or to top-level modules"; } - ostringstream msg; - msg << "ignoring invalid metadata '" << *s << "'"; - type->unit()->warning(s->file(), s->line(), InvalidMetadata, msg.str()); - newMetadata.remove(s); - } - } - return newMetadata; -} + return nullopt; + }, + }; + knownMetadata.emplace("python:package", std::move(packageInfo)); -void -Slice::Python::MetadataVisitor::reject(const ContainedPtr& cont) -{ - MetadataList localMetadata = cont->getMetadata(); + // "python:pkgdir" + MetadataInfo pkgdirInfo = { + .validOn = {typeid(Unit)}, + .acceptedArgumentKind = MetadataArgumentKind::RequiredTextArgument, + }; + knownMetadata.emplace("python:pkgdir", std::move(pkgdirInfo)); + + // "python:seq" + // We support 3 arguments to this metadata: "default", "list", and "tuple". + // We also allow users to omit the "seq" in the middle, ie. "python:seq:list" and "python:list" are equivalent. + MetadataInfo seqInfo = { + .validOn = {typeid(Sequence)}, + .acceptedArgumentKind = MetadataArgumentKind::SingleArgument, + .validArgumentValues = {{"default", "list", "tuple"}}, + .acceptedContext = MetadataApplicationContext::DefinitionsAndTypeReferences, + }; + knownMetadata.emplace("python:seq", std::move(seqInfo)); + MetadataInfo unqualifiedSeqInfo = { + .validOn = {typeid(Sequence)}, + .acceptedArgumentKind = MetadataArgumentKind::NoArguments, + .acceptedContext = MetadataApplicationContext::DefinitionsAndTypeReferences, + }; + knownMetadata.emplace("python:default", unqualifiedSeqInfo); + knownMetadata.emplace("python:list", unqualifiedSeqInfo); + knownMetadata.emplace("python:tuple", std::move(unqualifiedSeqInfo)); - for (auto p = localMetadata.begin(); p != localMetadata.end();) - { - MetadataPtr s = *p++; - if (s->directive().find("python:") == 0) - { - ostringstream msg; - msg << "ignoring invalid metadata '" << *s << "'"; - cont->unit()->warning(s->file(), s->line(), InvalidMetadata, msg.str()); - localMetadata.remove(s); - } - } - cont->setMetadata(std::move(localMetadata)); + // Pass this information off to the parser's metadata validation logic. + Slice::validateMetadata(unit, "python", knownMetadata); } diff --git a/cpp/src/slice2py/PythonUtil.h b/cpp/src/slice2py/PythonUtil.h index 520d19b690a..3ec130d7a03 100644 --- a/cpp/src/slice2py/PythonUtil.h +++ b/cpp/src/slice2py/PythonUtil.h @@ -55,6 +55,8 @@ namespace Slice::Python void printHeader(IceInternal::Output&); int compile(const std::vector&); + + void validateMetadata(const UnitPtr&); } #endif diff --git a/cpp/src/slice2rb/RubyUtil.cpp b/cpp/src/slice2rb/RubyUtil.cpp index d3516773999..fc1cad506bc 100644 --- a/cpp/src/slice2rb/RubyUtil.cpp +++ b/cpp/src/slice2rb/RubyUtil.cpp @@ -202,7 +202,7 @@ Slice::Ruby::CodeVisitor::visitModuleStart(const ModulePtr& p) { _out << sp << nl << "module "; // Ensure that Slice top-level modules are defined as top level modules in Ruby - if (dynamic_pointer_cast(p->container())) + if (p->isTopLevel()) { _out << "::"; } diff --git a/cpp/src/slice2swift/Gen.cpp b/cpp/src/slice2swift/Gen.cpp index c11e0cb8a42..5e6d414665a 100644 --- a/cpp/src/slice2swift/Gen.cpp +++ b/cpp/src/slice2swift/Gen.cpp @@ -102,10 +102,8 @@ Gen::ImportVisitor::ImportVisitor(IceInternal::Output& o) : out(o) {} bool Gen::ImportVisitor::visitModuleStart(const ModulePtr& p) { - // // Always import Ice module first if not building Ice - // - if (dynamic_pointer_cast(p->container()) && _imports.empty()) + if (p->isTopLevel() && _imports.empty()) { string swiftModule = getSwiftModule(p); if (swiftModule != "Ice") diff --git a/cpp/src/slice2swift/SwiftUtil.cpp b/cpp/src/slice2swift/SwiftUtil.cpp index e41929d2190..aca971c769f 100644 --- a/cpp/src/slice2swift/SwiftUtil.cpp +++ b/cpp/src/slice2swift/SwiftUtil.cpp @@ -249,12 +249,12 @@ Slice::getTopLevelModule(const ContainedPtr& cont) m = dynamic_pointer_cast(p); } - ContainerPtr c = p->container(); - p = dynamic_pointer_cast(c); // This cast fails for Unit. - if (!p) + if (p->isTopLevel()) { break; } + p = dynamic_pointer_cast(p->container()); + assert(p); } return m; } diff --git a/python/modules/IcePy/msbuild/icepy.vcxproj b/python/modules/IcePy/msbuild/icepy.vcxproj index 5277485bd26..e5eb63d500f 100644 --- a/python/modules/IcePy/msbuild/icepy.vcxproj +++ b/python/modules/IcePy/msbuild/icepy.vcxproj @@ -23,6 +23,7 @@ + diff --git a/python/modules/IcePy/msbuild/icepy.vcxproj.filters b/python/modules/IcePy/msbuild/icepy.vcxproj.filters index 0eb9afe79ef..7a800a38280 100644 --- a/python/modules/IcePy/msbuild/icepy.vcxproj.filters +++ b/python/modules/IcePy/msbuild/icepy.vcxproj.filters @@ -78,6 +78,9 @@ Source Files + + Source Files + Source Files diff --git a/python/test/Ice/custom/Test.ice b/python/test/Ice/custom/Test.ice index bcdb0cd4f50..fe1b881e3c7 100644 --- a/python/test/Ice/custom/Test.ice +++ b/python/test/Ice/custom/Test.ice @@ -96,11 +96,11 @@ module Test DoubleSeq1 opDoubleSeq(DoubleSeq1 v1, out DoubleSeq2 v2); ["python:memoryview:Custom.myBogusArrayNotExistsFactory"] BoolSeq1 opBogusArrayNotExistsFactory(); - ["python:memoryview:Custom.myBogusArrayThrowFactory"]BoolSeq1 opBogusArrayThrowFactory(); - ["python:memoryview:Custom.myBogusArrayType"]BoolSeq1 opBogusArrayType(); - ["python:memoryview:Custom.myBogusArrayNoneFactory"]BoolSeq1 opBogusArrayNoneFactory(); - ["python:memoryview:Custom.myBogusArraySignatureFactory"]BoolSeq1 opBogusArraySignatureFactory(); - ["python:memoryview:Custom.myNoCallableFactory"]BoolSeq1 opBogusArrayNoCallableFactory(); + ["python:memoryview:Custom.myBogusArrayThrowFactory"] BoolSeq1 opBogusArrayThrowFactory(); + ["python:memoryview:Custom.myBogusArrayType"] BoolSeq1 opBogusArrayType(); + ["python:memoryview:Custom.myBogusArrayNoneFactory"] BoolSeq1 opBogusArrayNoneFactory(); + ["python:memoryview:Custom.myBogusArraySignatureFactory"] BoolSeq1 opBogusArraySignatureFactory(); + ["python:memoryview:Custom.myNoCallableFactory"] BoolSeq1 opBogusArrayNoCallableFactory(); D opD(D d);