"Professional CMake" book suggest the following: "Targets should build successfully with or without compiler support for precompiled headers. It should be considered an optimization, not a requirement. In particular, do not explicitly include a precompile header (e.g. stdafx.h) in the source code, let CMake force-include an automatically generated precompile header on the compiler command line instead. This is more portable across the major compilers and is likely to be easier to maintain. It will also avoid warnings being generated from certain code checking tools like iwyu (include what you use)." Therefore, removed the "#include <PreCompiled.h>" from sources, also there is no need for the "#ifdef _PreComp_" anymore
1130 lines
32 KiB
C++
1130 lines
32 KiB
C++
/**************************************************************************
|
|
* *
|
|
* Copyright (c) 2022 FreeCAD Project Association *
|
|
* *
|
|
* This file is part of FreeCAD. *
|
|
* *
|
|
* FreeCAD is free software: you can redistribute it and/or modify it *
|
|
* under the terms of the GNU Lesser General Public License as *
|
|
* published by the Free Software Foundation, either version 2.1 of the *
|
|
* License, or (at your option) any later version. *
|
|
* *
|
|
* FreeCAD is distributed in the hope that it will be useful, but *
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
|
* Lesser General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Lesser General Public *
|
|
* License along with FreeCAD. If not, see *
|
|
* <https://www.gnu.org/licenses/>. *
|
|
* *
|
|
**************************************************************************/
|
|
|
|
|
|
#include "Metadata.h"
|
|
|
|
#include <Base/FileInfo.h>
|
|
#include <Base/Tools.h>
|
|
|
|
// inclusion of the generated files (generated out of MetadataPy.xml)
|
|
#include "MetadataPy.h"
|
|
#include "MetadataPy.cpp"
|
|
|
|
using namespace Base;
|
|
#ifndef XERCES_CPP_NAMESPACE_BEGIN
|
|
#define XERCES_CPP_NAMESPACE_QUALIFIER
|
|
using namespace XERCES_CPP_NAMESPACE;
|
|
#else
|
|
XERCES_CPP_NAMESPACE_USE
|
|
#endif
|
|
|
|
// Returns a string which represents the object e.g. when printed in Python
|
|
std::string MetadataPy::representation() const
|
|
{
|
|
MetadataPy::PointerType ptr = getMetadataPtr();
|
|
std::stringstream str;
|
|
str << "Metadata [Name=(";
|
|
str << ptr->name();
|
|
str << "), Description=(";
|
|
str << ptr->description();
|
|
if (!ptr->maintainer().empty()) {
|
|
str << "), Maintainer=(";
|
|
str << ptr->maintainer().front().name;
|
|
}
|
|
str << ")]";
|
|
|
|
return str.str();
|
|
}
|
|
|
|
PyObject* MetadataPy::PyMake(struct _typeobject*, PyObject*, PyObject*) // Python wrapper
|
|
{
|
|
return new MetadataPy(nullptr);
|
|
}
|
|
|
|
// constructor method
|
|
int MetadataPy::PyInit(PyObject* args, PyObject* /*kwd*/)
|
|
{
|
|
if (PyArg_ParseTuple(args, "")) {
|
|
setTwinPointer(new Metadata());
|
|
return 0;
|
|
}
|
|
|
|
// Data may be passed directly in as a bytes-like object buffer
|
|
PyErr_Clear();
|
|
Py_buffer dataBuffer;
|
|
if (PyArg_ParseTuple(args, "y*", &dataBuffer)) {
|
|
try {
|
|
// NB: This is making a copy of the buffer for simplicity, but that shouldn't be
|
|
// necessary. Use either a string_view or a span to avoid the copy in the future.
|
|
auto md =
|
|
new Metadata(std::string(static_cast<const char*>(dataBuffer.buf), dataBuffer.len));
|
|
setTwinPointer(md);
|
|
return 0;
|
|
}
|
|
catch (const Base::XMLBaseException&) {
|
|
// If the XML read failed, this might have been a path to a file, rather than a
|
|
// bytes-like object. Fall through to the next case.
|
|
}
|
|
}
|
|
|
|
// Main class constructor -- takes a file path, loads the metadata from it
|
|
PyErr_Clear();
|
|
char* filename;
|
|
if (PyArg_ParseTuple(args, "et", "utf-8", &filename)) {
|
|
try {
|
|
std::string utf8Name = std::string(filename);
|
|
PyMem_Free(filename);
|
|
|
|
auto md = new Metadata(Base::FileInfo::stringToPath(utf8Name));
|
|
setTwinPointer(md);
|
|
return 0;
|
|
}
|
|
catch (const Base::XMLBaseException& e) {
|
|
e.setPyException();
|
|
return -1;
|
|
}
|
|
catch (const XMLException& toCatch) {
|
|
char* message = XMLString::transcode(toCatch.getMessage());
|
|
std::string what = message;
|
|
XMLString::release(&message);
|
|
PyErr_SetString(Base::PyExc_FC_XMLBaseException, what.c_str());
|
|
return -1;
|
|
}
|
|
catch (const DOMException& toCatch) {
|
|
char* message = XMLString::transcode(toCatch.getMessage());
|
|
std::string what = message;
|
|
XMLString::release(&message);
|
|
PyErr_SetString(Base::PyExc_FC_XMLBaseException, what.c_str());
|
|
return -1;
|
|
}
|
|
catch (...) {
|
|
PyErr_SetString(Base::PyExc_FC_GeneralError, "Failed to create Metadata object");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
// Copy constructor
|
|
PyErr_Clear();
|
|
PyObject* o;
|
|
if (PyArg_ParseTuple(args, "O!", &(App::MetadataPy::Type), &o)) {
|
|
App::Metadata* a = static_cast<App::MetadataPy*>(o)->getMetadataPtr();
|
|
setTwinPointer(new Metadata(*a));
|
|
return 0;
|
|
}
|
|
|
|
PyErr_SetString(Base::PyExc_FC_GeneralError,
|
|
"metadata object or path to metadata file expected");
|
|
return -1;
|
|
}
|
|
|
|
Py::String MetadataPy::getName() const
|
|
{
|
|
return Py::String(getMetadataPtr()->name());
|
|
}
|
|
|
|
void MetadataPy::setName(Py::String args)
|
|
{
|
|
const char* name = nullptr;
|
|
if (!PyArg_Parse(args.ptr(), "z", &name)) {
|
|
throw Py::Exception();
|
|
}
|
|
if (name) {
|
|
getMetadataPtr()->setName(name);
|
|
}
|
|
else {
|
|
getMetadataPtr()->setName("");
|
|
}
|
|
}
|
|
|
|
Py::String MetadataPy::getVersion() const
|
|
{
|
|
return Py::String(getMetadataPtr()->version().str());
|
|
}
|
|
|
|
void MetadataPy::setVersion(Py::String args)
|
|
{
|
|
const char* name = nullptr;
|
|
if (!PyArg_Parse(args.ptr(), "z", &name)) {
|
|
throw Py::Exception();
|
|
}
|
|
if (!Base::Tools::isNullOrEmpty(name)) {
|
|
getMetadataPtr()->setVersion(App::Meta::Version(std::string(name)));
|
|
}
|
|
else {
|
|
getMetadataPtr()->setVersion(App::Meta::Version());
|
|
}
|
|
}
|
|
|
|
Py::String MetadataPy::getDate() const
|
|
{
|
|
return Py::String(getMetadataPtr()->date());
|
|
}
|
|
|
|
void MetadataPy::setDate(Py::String args)
|
|
{
|
|
const char* date = nullptr;
|
|
if (!PyArg_Parse(args.ptr(), "z", &date)) {
|
|
throw Py::Exception();
|
|
}
|
|
if (date) {
|
|
getMetadataPtr()->setDate(date);
|
|
}
|
|
else {
|
|
getMetadataPtr()->setDate("");
|
|
}
|
|
}
|
|
|
|
Py::String MetadataPy::getDescription() const
|
|
{
|
|
return Py::String(getMetadataPtr()->description());
|
|
}
|
|
|
|
void MetadataPy::setDescription(Py::String args)
|
|
{
|
|
const char* description = nullptr;
|
|
if (!PyArg_Parse(args.ptr(), "s", &description)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->setDescription(description);
|
|
}
|
|
|
|
Py::String MetadataPy::getType() const
|
|
{
|
|
return Py::String(getMetadataPtr()->type());
|
|
}
|
|
|
|
void MetadataPy::setType(Py::String args)
|
|
{
|
|
const char* type = nullptr;
|
|
if (!PyArg_Parse(args.ptr(), "s", &type)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->setType(type);
|
|
}
|
|
|
|
Py::List MetadataPy::getMaintainer() const
|
|
{
|
|
auto maintainers = getMetadataPtr()->maintainer();
|
|
Py::List pyMaintainers;
|
|
for (const auto& m : maintainers) {
|
|
Py::Dict pyMaintainer;
|
|
pyMaintainer["name"] = Py::String(m.name);
|
|
pyMaintainer["email"] = Py::String(m.email);
|
|
pyMaintainers.append(pyMaintainer);
|
|
}
|
|
return pyMaintainers;
|
|
}
|
|
|
|
void MetadataPy::setMaintainer(Py::List args)
|
|
{
|
|
PyObject* list = nullptr;
|
|
if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
getMetadataPtr()->clearMaintainer();
|
|
Py::List maintainers(list);
|
|
for (const auto& m : maintainers) {
|
|
Py::Dict pyMaintainer(m);
|
|
std::string name = pyMaintainer["name"].str();
|
|
std::string email = pyMaintainer["email"].str();
|
|
getMetadataPtr()->addMaintainer(App::Meta::Contact(name, email));
|
|
}
|
|
}
|
|
|
|
PyObject* MetadataPy::addMaintainer(PyObject* args)
|
|
{
|
|
const char* name = nullptr;
|
|
const char* email = nullptr;
|
|
if (!PyArg_ParseTuple(args, "ss", &name, &email)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->addMaintainer(App::Meta::Contact(name, email));
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
PyObject* MetadataPy::removeMaintainer(PyObject* args)
|
|
{
|
|
const char* name = nullptr;
|
|
const char* email = nullptr;
|
|
if (!PyArg_ParseTuple(args, "ss", &name, &email)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->removeMaintainer(App::Meta::Contact(name, email));
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
|
|
Py::List MetadataPy::getAuthor() const
|
|
{
|
|
auto authors = getMetadataPtr()->author();
|
|
Py::List pyAuthors;
|
|
for (const auto& a : authors) {
|
|
Py::Dict pyAuthor;
|
|
pyAuthor["name"] = Py::String(a.name);
|
|
pyAuthor["email"] = Py::String(a.email);
|
|
pyAuthors.append(pyAuthor);
|
|
}
|
|
return pyAuthors;
|
|
}
|
|
|
|
void MetadataPy::setAuthor(Py::List args)
|
|
{
|
|
PyObject* list = nullptr;
|
|
if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
getMetadataPtr()->clearAuthor();
|
|
Py::List authors(list);
|
|
for (const auto& a : authors) {
|
|
Py::Dict pyAuthor(a);
|
|
std::string name = pyAuthor["name"].str();
|
|
std::string email = pyAuthor["email"].str();
|
|
getMetadataPtr()->addAuthor(App::Meta::Contact(name, email));
|
|
}
|
|
}
|
|
|
|
PyObject* MetadataPy::addAuthor(PyObject* args)
|
|
{
|
|
const char* name = nullptr;
|
|
const char* email = nullptr;
|
|
if (!PyArg_ParseTuple(args, "ss", &name, &email)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->addAuthor(App::Meta::Contact(name, email));
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
PyObject* MetadataPy::removeAuthor(PyObject* args)
|
|
{
|
|
const char* name = nullptr;
|
|
const char* email = nullptr;
|
|
if (!PyArg_ParseTuple(args, "ss", &name, &email)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->removeAuthor(App::Meta::Contact(name, email));
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
Py::List MetadataPy::getLicense() const
|
|
{
|
|
auto licenses = getMetadataPtr()->license();
|
|
Py::List pyLicenses;
|
|
for (const auto& lic : licenses) {
|
|
Py::Dict pyLicense;
|
|
pyLicense["name"] = Py::String(lic.name);
|
|
pyLicense["file"] = Py::String(lic.file.string());
|
|
pyLicenses.append(pyLicense);
|
|
}
|
|
return pyLicenses;
|
|
}
|
|
|
|
void MetadataPy::setLicense(Py::List args)
|
|
{
|
|
PyObject* list = nullptr;
|
|
if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
getMetadataPtr()->clearLicense();
|
|
Py::List licenses(list);
|
|
for (const auto& l : licenses) {
|
|
Py::Dict pyLicense(l);
|
|
std::string name = pyLicense["name"].str();
|
|
std::string path = pyLicense["file"].str();
|
|
getMetadataPtr()->addLicense(App::Meta::License(name, path));
|
|
}
|
|
}
|
|
|
|
PyObject* MetadataPy::addLicense(PyObject* args)
|
|
{
|
|
const char* shortCode = nullptr;
|
|
const char* path = nullptr;
|
|
if (!PyArg_ParseTuple(args, "ss", &shortCode, &path)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->addLicense(App::Meta::License(shortCode, path));
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
PyObject* MetadataPy::removeLicense(PyObject* args)
|
|
{
|
|
const char* shortCode = nullptr;
|
|
const char* path = nullptr;
|
|
if (!PyArg_ParseTuple(args, "ss", &shortCode, &path)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->removeLicense(App::Meta::License(shortCode, path));
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
Py::List MetadataPy::getUrls() const
|
|
{
|
|
auto urls = getMetadataPtr()->url();
|
|
Py::List pyUrls;
|
|
for (const auto& url : urls) {
|
|
Py::Dict pyUrl;
|
|
pyUrl["location"] = Py::String(url.location);
|
|
switch (url.type) {
|
|
case Meta::UrlType::website:
|
|
pyUrl["type"] = Py::String("website");
|
|
break;
|
|
case Meta::UrlType::repository:
|
|
pyUrl["type"] = Py::String("repository");
|
|
break;
|
|
case Meta::UrlType::bugtracker:
|
|
pyUrl["type"] = Py::String("bugtracker");
|
|
break;
|
|
case Meta::UrlType::readme:
|
|
pyUrl["type"] = Py::String("readme");
|
|
break;
|
|
case Meta::UrlType::documentation:
|
|
pyUrl["type"] = Py::String("documentation");
|
|
break;
|
|
case Meta::UrlType::discussion:
|
|
pyUrl["type"] = Py::String("discussion");
|
|
break;
|
|
default:
|
|
pyUrl["type"] = Py::String("unknown");
|
|
break;
|
|
}
|
|
if (url.type == Meta::UrlType::repository) {
|
|
pyUrl["branch"] = Py::String(url.branch);
|
|
}
|
|
pyUrls.append(pyUrl);
|
|
}
|
|
return pyUrls;
|
|
}
|
|
|
|
void MetadataPy::setUrls(Py::List args)
|
|
{
|
|
PyObject* list = nullptr;
|
|
if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
getMetadataPtr()->clearUrl();
|
|
Py::List urls(list);
|
|
for (const auto& url : urls) {
|
|
Py::Dict pyUrl(url);
|
|
std::string location = pyUrl["location"].str();
|
|
std::string typeAsString = pyUrl["type"].str();
|
|
std::string branch = pyUrl["branch"].str();
|
|
auto newUrl = App::Meta::Url(location, Meta::UrlType::website);
|
|
if (typeAsString == "website") {
|
|
newUrl.type = Meta::UrlType::website;
|
|
}
|
|
else if (typeAsString == "repository") {
|
|
newUrl.type = Meta::UrlType::repository;
|
|
newUrl.branch = branch;
|
|
}
|
|
else if (typeAsString == "bugtracker") {
|
|
newUrl.type = Meta::UrlType::bugtracker;
|
|
}
|
|
else if (typeAsString == "readme") {
|
|
newUrl.type = Meta::UrlType::readme;
|
|
}
|
|
else if (typeAsString == "documentation") {
|
|
newUrl.type = Meta::UrlType::documentation;
|
|
}
|
|
else if (typeAsString == "discussion") {
|
|
newUrl.type = Meta::UrlType::discussion;
|
|
}
|
|
else {
|
|
PyErr_SetString(Base::PyExc_FC_GeneralError, "Unrecognized URL type");
|
|
return;
|
|
}
|
|
getMetadataPtr()->addUrl(newUrl);
|
|
}
|
|
}
|
|
|
|
App::Meta::Url urlFromStrings(const char* urlTypeCharStar, const char* link, const char* branch)
|
|
{
|
|
std::string urlTypeString(urlTypeCharStar);
|
|
App::Meta::UrlType urlType {App::Meta::UrlType::documentation};
|
|
if (urlTypeString == "repository") {
|
|
urlType = App::Meta::UrlType::repository;
|
|
}
|
|
else if (urlTypeString == "bugtracker") {
|
|
urlType = App::Meta::UrlType::bugtracker;
|
|
}
|
|
else if (urlTypeString == "documentation") {
|
|
urlType = App::Meta::UrlType::documentation;
|
|
}
|
|
else if (urlTypeString == "readme") {
|
|
urlType = App::Meta::UrlType::readme;
|
|
}
|
|
else if (urlTypeString == "website") {
|
|
urlType = App::Meta::UrlType::website;
|
|
}
|
|
|
|
App::Meta::Url url(link, urlType);
|
|
if (urlType == App::Meta::UrlType::repository) {
|
|
url.branch = std::string(branch);
|
|
}
|
|
|
|
return url;
|
|
}
|
|
|
|
PyObject* MetadataPy::addUrl(PyObject* args)
|
|
{
|
|
const char* urlTypeCharStar = nullptr;
|
|
const char* link = nullptr;
|
|
const char* branch = nullptr;
|
|
if (!PyArg_ParseTuple(args, "ss|s", &urlTypeCharStar, &link, &branch)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
getMetadataPtr()->addUrl(urlFromStrings(urlTypeCharStar, link, branch));
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
PyObject* MetadataPy::removeUrl(PyObject* args)
|
|
{
|
|
const char* urlTypeCharStar = nullptr;
|
|
const char* link = nullptr;
|
|
const char* branch = nullptr;
|
|
if (!PyArg_ParseTuple(args, "ss|s", &urlTypeCharStar, &link, &branch)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
getMetadataPtr()->removeUrl(urlFromStrings(urlTypeCharStar, link, branch));
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
Py::Object dependencyToPyObject(const Meta::Dependency& d)
|
|
{
|
|
Py::Dict pyDependency;
|
|
pyDependency["package"] = Py::String(d.package);
|
|
pyDependency["version_lt"] = Py::String(d.version_lt);
|
|
pyDependency["version_lte"] = Py::String(d.version_lte);
|
|
pyDependency["version_eq"] = Py::String(d.version_eq);
|
|
pyDependency["version_gt"] = Py::String(d.version_gt);
|
|
pyDependency["version_gte"] = Py::String(d.version_gte);
|
|
pyDependency["condition"] = Py::String(d.condition);
|
|
pyDependency["optional"] = Py::Boolean(d.optional);
|
|
switch (d.dependencyType) {
|
|
case App::Meta::DependencyType::automatic:
|
|
pyDependency["type"] = Py::String("automatic");
|
|
break;
|
|
case App::Meta::DependencyType::addon:
|
|
pyDependency["type"] = Py::String("addon");
|
|
break;
|
|
case App::Meta::DependencyType::internal:
|
|
pyDependency["type"] = Py::String("internal");
|
|
break;
|
|
case App::Meta::DependencyType::python:
|
|
pyDependency["type"] = Py::String("python");
|
|
break;
|
|
}
|
|
return pyDependency;
|
|
}
|
|
|
|
Meta::Dependency pyObjectToDependency(const Py::Object& d)
|
|
{
|
|
Py::Dict pyDependency(d);
|
|
Meta::Dependency result;
|
|
result.package = pyDependency["package"].str();
|
|
if (pyDependency.hasKey("version_lt")) {
|
|
result.version_lt = pyDependency["version_lt"].str();
|
|
}
|
|
if (pyDependency.hasKey("version_lte")) {
|
|
result.version_lte = pyDependency["version_lte"].str();
|
|
}
|
|
if (pyDependency.hasKey("version_eq")) {
|
|
result.version_eq = pyDependency["version_eq"].str();
|
|
}
|
|
if (pyDependency.hasKey("version_gt")) {
|
|
result.version_gt = pyDependency["version_gt"].str();
|
|
}
|
|
if (pyDependency.hasKey("version_gte")) {
|
|
result.version_gte = pyDependency["version_gte"].str();
|
|
}
|
|
if (pyDependency.hasKey("condition")) {
|
|
result.condition = pyDependency["condition"].str();
|
|
}
|
|
if (pyDependency.hasKey("optional")) {
|
|
result.optional = Py::Boolean(pyDependency["optional"]).as_bool();
|
|
}
|
|
if (pyDependency.hasKey("type")) {
|
|
if (pyDependency["type"].str() == Py::String("automatic")) {
|
|
result.dependencyType = App::Meta::DependencyType::automatic;
|
|
}
|
|
else if (pyDependency["type"].str() == Py::String("internal")) {
|
|
result.dependencyType = App::Meta::DependencyType::internal;
|
|
}
|
|
else if (pyDependency["type"].str() == Py::String("addon")) {
|
|
result.dependencyType = App::Meta::DependencyType::addon;
|
|
}
|
|
else if (pyDependency["type"].str() == Py::String("python")) {
|
|
result.dependencyType = App::Meta::DependencyType::python;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Py::List MetadataPy::getDepend() const
|
|
{
|
|
auto dependencies = getMetadataPtr()->depend();
|
|
Py::List pyDependencies;
|
|
for (const auto& d : dependencies) {
|
|
pyDependencies.append(dependencyToPyObject(d));
|
|
}
|
|
return pyDependencies;
|
|
}
|
|
|
|
void MetadataPy::setDepend(Py::List args)
|
|
{
|
|
PyObject* list = nullptr;
|
|
if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
getMetadataPtr()->clearDepend();
|
|
Py::List deps(list);
|
|
for (const auto& dep : deps) {
|
|
Py::Dict pyDep(dep);
|
|
getMetadataPtr()->addDepend(pyObjectToDependency(pyDep));
|
|
}
|
|
}
|
|
|
|
PyObject* MetadataPy::addDepend(PyObject* args)
|
|
{
|
|
PyObject* dictionary = nullptr;
|
|
if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) {
|
|
throw Py::Exception();
|
|
}
|
|
Py::Dict pyDep(dictionary);
|
|
getMetadataPtr()->addDepend(pyObjectToDependency(pyDep));
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
PyObject* MetadataPy::removeDepend(PyObject* args)
|
|
{
|
|
PyObject* dictionary = nullptr;
|
|
if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) {
|
|
throw Py::Exception();
|
|
}
|
|
Py::Dict pyDep(dictionary);
|
|
getMetadataPtr()->removeDepend(pyObjectToDependency(pyDep));
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
Py::List MetadataPy::getConflict() const
|
|
{
|
|
auto dependencies = getMetadataPtr()->conflict();
|
|
Py::List pyDependencies;
|
|
for (const auto& d : dependencies) {
|
|
pyDependencies.append(dependencyToPyObject(d));
|
|
}
|
|
return pyDependencies;
|
|
}
|
|
|
|
void MetadataPy::setConflict(Py::List args)
|
|
{
|
|
PyObject* list = nullptr;
|
|
if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
getMetadataPtr()->clearConflict();
|
|
Py::List deps(list);
|
|
for (const auto& dep : deps) {
|
|
Py::Dict pyDep(dep);
|
|
getMetadataPtr()->addConflict(pyObjectToDependency(pyDep));
|
|
}
|
|
}
|
|
|
|
PyObject* MetadataPy::addConflict(PyObject* args)
|
|
{
|
|
PyObject* dictionary = nullptr;
|
|
if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) {
|
|
throw Py::Exception();
|
|
}
|
|
Py::Dict pyDep(dictionary);
|
|
getMetadataPtr()->addConflict(pyObjectToDependency(pyDep));
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
PyObject* MetadataPy::removeConflict(PyObject* args)
|
|
{
|
|
PyObject* dictionary = nullptr;
|
|
if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) {
|
|
throw Py::Exception();
|
|
}
|
|
Py::Dict pyDep(dictionary);
|
|
getMetadataPtr()->removeConflict(pyObjectToDependency(pyDep));
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
Py::List MetadataPy::getReplace() const
|
|
{
|
|
auto dependencies = getMetadataPtr()->replace();
|
|
Py::List pyDependencies;
|
|
for (const auto& d : dependencies) {
|
|
pyDependencies.append(dependencyToPyObject(d));
|
|
}
|
|
return pyDependencies;
|
|
}
|
|
|
|
void MetadataPy::setReplace(Py::List args)
|
|
{
|
|
PyObject* list = nullptr;
|
|
if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
getMetadataPtr()->clearReplace();
|
|
Py::List deps(list);
|
|
for (const auto& dep : deps) {
|
|
Py::Dict pyDep(dep);
|
|
getMetadataPtr()->addReplace(pyObjectToDependency(pyDep));
|
|
}
|
|
}
|
|
|
|
PyObject* MetadataPy::addReplace(PyObject* args)
|
|
{
|
|
PyObject* dictionary = nullptr;
|
|
if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) {
|
|
throw Py::Exception();
|
|
}
|
|
Py::Dict pyDep(dictionary);
|
|
getMetadataPtr()->addReplace(pyObjectToDependency(pyDep));
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
PyObject* MetadataPy::removeReplace(PyObject* args)
|
|
{
|
|
PyObject* dictionary = nullptr;
|
|
if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary)) {
|
|
throw Py::Exception();
|
|
}
|
|
Py::Dict pyDep(dictionary);
|
|
getMetadataPtr()->removeReplace(pyObjectToDependency(pyDep));
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
// Tag, icon, classname, file
|
|
|
|
Py::List MetadataPy::getTag() const
|
|
{
|
|
auto tags = getMetadataPtr()->tag();
|
|
Py::List pyTags;
|
|
for (const auto& t : tags) {
|
|
pyTags.append(Py::String(t));
|
|
}
|
|
return pyTags;
|
|
}
|
|
|
|
void MetadataPy::setTag(Py::List args)
|
|
{
|
|
PyObject* list = nullptr;
|
|
if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
getMetadataPtr()->clearTag();
|
|
Py::List tags(list);
|
|
for (const auto& tag : tags) {
|
|
Py::String pyTag(tag);
|
|
getMetadataPtr()->addTag(pyTag.as_std_string());
|
|
}
|
|
}
|
|
|
|
PyObject* MetadataPy::addTag(PyObject* args)
|
|
{
|
|
const char* tag = nullptr;
|
|
if (!PyArg_ParseTuple(args, "s", &tag)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->addTag(tag);
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
PyObject* MetadataPy::removeTag(PyObject* args)
|
|
{
|
|
const char* tag = nullptr;
|
|
if (!PyArg_ParseTuple(args, "s", &tag)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->removeTag(tag);
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
Py::String MetadataPy::getIcon() const
|
|
{
|
|
return Py::String(getMetadataPtr()->icon().string());
|
|
}
|
|
|
|
void MetadataPy::setIcon(Py::String args)
|
|
{
|
|
const char* name;
|
|
if (!PyArg_Parse(args.ptr(), "s", &name)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->setIcon(name);
|
|
}
|
|
|
|
Py::String MetadataPy::getClassname() const
|
|
{
|
|
return Py::String(getMetadataPtr()->classname());
|
|
}
|
|
|
|
void MetadataPy::setClassname(Py::String args)
|
|
{
|
|
const char* name;
|
|
if (!PyArg_Parse(args.ptr(), "s", &name)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->setClassname(name);
|
|
}
|
|
|
|
Py::String MetadataPy::getSubdirectory() const
|
|
{
|
|
return Py::String(getMetadataPtr()->subdirectory().string());
|
|
}
|
|
|
|
void MetadataPy::setSubdirectory(Py::String args)
|
|
{
|
|
const char* name;
|
|
if (!PyArg_Parse(args.ptr(), "s", &name)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->setSubdirectory(name);
|
|
}
|
|
|
|
Py::List MetadataPy::getFile() const
|
|
{
|
|
auto files = getMetadataPtr()->file();
|
|
Py::List pyFiles;
|
|
for (const auto& f : files) {
|
|
pyFiles.append(Py::String(f.string()));
|
|
}
|
|
return pyFiles;
|
|
}
|
|
|
|
void MetadataPy::setFile(Py::List args)
|
|
{
|
|
PyObject* list = nullptr;
|
|
if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
getMetadataPtr()->clearTag();
|
|
Py::List files(list);
|
|
for (const auto& file : files) {
|
|
Py::String pyFile(file);
|
|
getMetadataPtr()->addFile(pyFile.as_std_string());
|
|
}
|
|
}
|
|
|
|
PyObject* MetadataPy::addFile(PyObject* args)
|
|
{
|
|
const char* file = nullptr;
|
|
if (!PyArg_ParseTuple(args, "s", &file)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->addFile(file);
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
PyObject* MetadataPy::removeFile(PyObject* args)
|
|
{
|
|
const char* file = nullptr;
|
|
if (!PyArg_ParseTuple(args, "s", &file)) {
|
|
throw Py::Exception();
|
|
}
|
|
getMetadataPtr()->removeFile(file);
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
|
|
Py::Dict MetadataPy::getContent() const
|
|
{
|
|
auto content = getMetadataPtr()->content();
|
|
std::set<std::string> keys;
|
|
for (const auto& item : content) {
|
|
keys.insert(item.first);
|
|
}
|
|
|
|
// For the Python, we'll use a dictionary of lists to store the content components:
|
|
Py::Dict pyContent;
|
|
for (const auto& key : keys) {
|
|
Py::List pyContentForKey;
|
|
auto elements = content.equal_range(key);
|
|
for (auto& element = elements.first; element != elements.second; ++element) {
|
|
auto contentMetadataItem = new MetadataPy(new Metadata(element->second));
|
|
pyContentForKey.append(Py::asObject(contentMetadataItem));
|
|
}
|
|
pyContent[key] = pyContentForKey;
|
|
}
|
|
return pyContent;
|
|
}
|
|
|
|
void MetadataPy::setContent(Py::Dict arg)
|
|
{
|
|
PyObject* obj = nullptr;
|
|
if (!PyArg_Parse(arg.ptr(), "O!", &PyList_Type, &obj)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
getMetadataPtr()->clearContent();
|
|
Py::Dict outerDict(obj);
|
|
for (const auto& pyContentType : outerDict) {
|
|
auto contentType = Py::String(pyContentType.first).as_std_string();
|
|
auto contentList = Py::List(pyContentType.second);
|
|
for (const auto& contentItem : contentList) {
|
|
auto item = static_cast<MetadataPy*>(contentItem.ptr());
|
|
getMetadataPtr()->addContentItem(contentType, *(item->getMetadataPtr()));
|
|
}
|
|
}
|
|
}
|
|
|
|
PyObject* MetadataPy::getGenericMetadata(PyObject* args)
|
|
{
|
|
const char* name;
|
|
if (!PyArg_ParseTuple(args, "s", &name)) {
|
|
return nullptr;
|
|
}
|
|
|
|
auto gm = (*getMetadataPtr())[name];
|
|
Py::List pyGenericMetadata;
|
|
for (const auto& item : gm) {
|
|
Py::Dict pyItem;
|
|
pyItem["contents"] = Py::String(item.contents);
|
|
Py::Dict pyAttributes;
|
|
for (const auto& attribute : item.attributes) {
|
|
pyAttributes[attribute.first] = Py::String(attribute.second);
|
|
}
|
|
pyItem["attributes"] = pyAttributes;
|
|
pyGenericMetadata.append(pyItem);
|
|
}
|
|
return Py::new_reference_to(pyGenericMetadata);
|
|
}
|
|
|
|
Py::String MetadataPy::getFreeCADMin() const
|
|
{
|
|
return Py::String(getMetadataPtr()->freecadmin().str());
|
|
}
|
|
|
|
void MetadataPy::setFreeCADMin(Py::String args)
|
|
{
|
|
char* version = nullptr;
|
|
PyObject* p = args.ptr();
|
|
if (!PyArg_Parse(p, "z", &version)) {
|
|
throw Py::Exception();
|
|
}
|
|
if (version) {
|
|
getMetadataPtr()->setFreeCADMin(App::Meta::Version(version));
|
|
}
|
|
else {
|
|
getMetadataPtr()->setFreeCADMin(App::Meta::Version());
|
|
}
|
|
}
|
|
|
|
Py::String MetadataPy::getFreeCADMax() const
|
|
{
|
|
return Py::String(getMetadataPtr()->freecadmax().str());
|
|
}
|
|
|
|
void MetadataPy::setFreeCADMax(Py::String args)
|
|
{
|
|
char* version = nullptr;
|
|
PyObject* p = args.ptr();
|
|
if (!PyArg_Parse(p, "z", &version)) {
|
|
throw Py::Exception();
|
|
}
|
|
|
|
if (version) {
|
|
getMetadataPtr()->setFreeCADMax(App::Meta::Version(version));
|
|
}
|
|
else {
|
|
getMetadataPtr()->setFreeCADMax(App::Meta::Version());
|
|
}
|
|
}
|
|
|
|
Py::String MetadataPy::getPythonMin() const
|
|
{
|
|
return Py::String(getMetadataPtr()->pythonmin().str());
|
|
}
|
|
|
|
void MetadataPy::setPythonMin(Py::String args)
|
|
{
|
|
char* version = nullptr;
|
|
PyObject* p = args.ptr();
|
|
if (!PyArg_Parse(p, "z", &version)) {
|
|
throw Py::Exception();
|
|
}
|
|
if (version) {
|
|
getMetadataPtr()->setPythonMin(App::Meta::Version(version));
|
|
}
|
|
else {
|
|
getMetadataPtr()->setPythonMin(App::Meta::Version());
|
|
}
|
|
}
|
|
|
|
PyObject* MetadataPy::getFirstSupportedFreeCADVersion(PyObject* p)
|
|
{
|
|
if (!PyArg_ParseTuple(p, "")) {
|
|
return nullptr;
|
|
}
|
|
|
|
// Short-circuit: if the toplevel sets a version, then the lower-levels are overridden
|
|
if (getMetadataPtr()->freecadmin() != App::Meta::Version()) {
|
|
return Py::new_reference_to(Py::String(getMetadataPtr()->freecadmin().str()));
|
|
}
|
|
|
|
auto content = getMetadataPtr()->content();
|
|
auto result = App::Meta::Version();
|
|
for (const auto& item : content) {
|
|
auto minVersion = item.second.freecadmin();
|
|
if (minVersion != App::Meta::Version()) {
|
|
if (result == App::Meta::Version() || minVersion < result) {
|
|
result = minVersion;
|
|
}
|
|
}
|
|
}
|
|
if (result != App::Meta::Version()) {
|
|
return Py::new_reference_to(Py::String(result.str()));
|
|
}
|
|
else {
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
}
|
|
|
|
PyObject* MetadataPy::getLastSupportedFreeCADVersion(PyObject* p)
|
|
{
|
|
if (!PyArg_ParseTuple(p, "")) {
|
|
return nullptr;
|
|
}
|
|
|
|
// Short-circuit: if the toplevel sets a version, then the lower-levels are overridden
|
|
if (getMetadataPtr()->freecadmax() != App::Meta::Version()) {
|
|
return Py::new_reference_to(Py::String(getMetadataPtr()->freecadmax().str()));
|
|
}
|
|
|
|
auto content = getMetadataPtr()->content();
|
|
auto result = App::Meta::Version();
|
|
for (const auto& item : content) {
|
|
auto maxVersion = item.second.freecadmax();
|
|
if (maxVersion != App::Meta::Version()) {
|
|
if (result == App::Meta::Version() || maxVersion > result) {
|
|
result = maxVersion;
|
|
}
|
|
}
|
|
}
|
|
if (result != App::Meta::Version()) {
|
|
return Py::new_reference_to(Py::String(result.str()));
|
|
}
|
|
else {
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
}
|
|
|
|
PyObject* MetadataPy::supportsCurrentFreeCAD(PyObject* p)
|
|
{
|
|
if (!PyArg_ParseTuple(p, "")) {
|
|
return nullptr;
|
|
}
|
|
|
|
bool result = getMetadataPtr()->supportsCurrentFreeCAD();
|
|
return Py::new_reference_to(Py::Boolean(result));
|
|
}
|
|
|
|
PyObject* MetadataPy::addContentItem(PyObject* arg)
|
|
{
|
|
char* contentType = nullptr;
|
|
PyObject* contentItem = nullptr;
|
|
if (!PyArg_ParseTuple(arg, "sO!", &contentType, &(App::MetadataPy::Type), &contentItem)) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (!contentItem || !contentType) {
|
|
return nullptr;
|
|
}
|
|
auto item = static_cast<MetadataPy*>(contentItem);
|
|
getMetadataPtr()->addContentItem(contentType, *(item->getMetadataPtr()));
|
|
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
PyObject* MetadataPy::removeContentItem(PyObject* arg)
|
|
{
|
|
char* contentType = nullptr;
|
|
char* contentName = nullptr;
|
|
if (!PyArg_ParseTuple(arg, "ss", &contentType, &contentName)) {
|
|
return nullptr;
|
|
}
|
|
if (contentType && contentName) {
|
|
getMetadataPtr()->removeContentItem(contentType, contentName);
|
|
}
|
|
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
PyObject* MetadataPy::write(PyObject* args)
|
|
{
|
|
char* filename = nullptr;
|
|
if (!PyArg_ParseTuple(args, "s", &filename)) {
|
|
return nullptr;
|
|
}
|
|
getMetadataPtr()->write(filename);
|
|
|
|
Py_INCREF(Py_None);
|
|
return Py_None;
|
|
}
|
|
|
|
|
|
PyObject* MetadataPy::getCustomAttributes(const char* /*attr*/) const
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
int MetadataPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
|
{
|
|
return 0;
|
|
}
|