FreeCAD

Форк
0
/
MetadataPyImp.cpp 
1029 строк · 31.1 Кб
1
/**************************************************************************
2
*                                                                         *
3
*   Copyright (c) 2022 FreeCAD Project Association                        *
4
*                                                                         *
5
*   This file is part of FreeCAD.                                         *
6
*                                                                         *
7
*   FreeCAD is free software: you can redistribute it and/or modify it    *
8
*   under the terms of the GNU Lesser General Public License as           *
9
*   published by the Free Software Foundation, either version 2.1 of the  *
10
*   License, or (at your option) any later version.                       *
11
*                                                                         *
12
*   FreeCAD is distributed in the hope that it will be useful, but        *
13
*   WITHOUT ANY WARRANTY; without even the implied warranty of            *
14
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      *
15
*   Lesser General Public License for more details.                       *
16
*                                                                         *
17
*   You should have received a copy of the GNU Lesser General Public      *
18
*   License along with FreeCAD. If not, see                               *
19
*   <https://www.gnu.org/licenses/>.                                      *
20
*                                                                         *
21
**************************************************************************/
22

23
#include "PreCompiled.h"
24

25
#include "Metadata.h"
26
#include <Base/FileInfo.h>
27

28
// inclusion of the generated files (generated out of MetadataPy.xml)
29
#include "MetadataPy.h"
30
#include "MetadataPy.cpp"
31

32
using namespace Base;
33
#ifndef XERCES_CPP_NAMESPACE_BEGIN
34
#define XERCES_CPP_NAMESPACE_QUALIFIER
35
using namespace XERCES_CPP_NAMESPACE;
36
#else
37
XERCES_CPP_NAMESPACE_USE
38
#endif
39

40
// Returns a string which represents the object e.g. when printed in Python
41
std::string MetadataPy::representation() const
42
{
43
    MetadataPy::PointerType ptr = getMetadataPtr();
44
    std::stringstream str;
45
    str << "Metadata [Name=(";
46
    str << ptr->name();
47
    str << "), Description=(";
48
    str << ptr->description();
49
    if (!ptr->maintainer().empty()) {
50
        str << "), Maintainer=(";
51
        str << ptr->maintainer().front().name;
52
    }
53
    str << ")]";
54

55
    return str.str();
56
}
57

58
PyObject *MetadataPy::PyMake(struct _typeobject *, PyObject *, PyObject *)// Python wrapper
59
{
60
    return new MetadataPy(nullptr);
61
}
62

63
// constructor method
64
int MetadataPy::PyInit(PyObject *args, PyObject * /*kwd*/)
65
{
66
    if (PyArg_ParseTuple(args, "")) {
67
        setTwinPointer(new Metadata());
68
        return 0;
69
    }
70

71
    // Data may be passed directly in as a bytes-like object buffer
72
    PyErr_Clear();
73
    Py_buffer dataBuffer;
74
    if (PyArg_ParseTuple(args, "y*", &dataBuffer)) {
75
        try {
76
            // NB: This is making a copy of the buffer for simplicity, but that shouldn't be
77
            // necessary. Use either a string_view or a span to avoid the copy in the future.
78
            auto md = new Metadata(
79
                std::string(static_cast<const char*>(dataBuffer.buf), dataBuffer.len)
80
            );
81
            setTwinPointer(md);
82
            return 0;
83
        }
84
        catch (const Base::XMLBaseException&) {
85
            // If the XML read failed, this might have been a path to a file, rather than a
86
            // bytes-like object. Fall through to the next case.
87
        }
88
    }
89

90
    // Main class constructor -- takes a file path, loads the metadata from it
91
    PyErr_Clear();
92
    char *filename;
93
    if (PyArg_ParseTuple(args, "et", "utf-8", &filename)) {
94
        try {
95
            std::string utf8Name = std::string(filename);
96
            PyMem_Free(filename);
97

98
            auto md = new Metadata(Base::FileInfo::stringToPath(utf8Name));
99
            setTwinPointer(md);
100
            return 0;
101
        }
102
        catch (const Base::XMLBaseException &e) {
103
            e.setPyException();
104
            return -1;
105
        }
106
        catch (const XMLException &toCatch) {
107
            char *message = XMLString::transcode(toCatch.getMessage());
108
            std::string what = message;
109
            XMLString::release(&message);
110
            PyErr_SetString(Base::PyExc_FC_XMLBaseException, what.c_str());
111
            return -1;
112
        }
113
        catch (const DOMException &toCatch) {
114
            char *message = XMLString::transcode(toCatch.getMessage());
115
            std::string what = message;
116
            XMLString::release(&message);
117
            PyErr_SetString(Base::PyExc_FC_XMLBaseException, what.c_str());
118
            return -1;
119
        }
120
        catch (...) {
121
            PyErr_SetString(Base::PyExc_FC_GeneralError, "Failed to create Metadata object");
122
            return -1;
123
        }
124
    }
125

126
    // Copy constructor
127
    PyErr_Clear();
128
    PyObject *o;
129
    if (PyArg_ParseTuple(args, "O!", &(App::MetadataPy::Type), &o)) {
130
        App::Metadata *a = static_cast<App::MetadataPy *>(o)->getMetadataPtr();
131
        setTwinPointer(new Metadata(*a));
132
        return 0;
133
    }
134

135
    PyErr_SetString(Base::PyExc_FC_GeneralError, "metadata object or path to metadata file expected");
136
    return -1;
137
}
138

139
Py::Object MetadataPy::getName() const
140
{
141
    return Py::String(getMetadataPtr()->name());
142
}
143

144
void MetadataPy::setName(Py::Object args)
145
{
146
    const char *name = nullptr;
147
    if (!PyArg_Parse(args.ptr(), "z", &name)) {
148
        throw Py::Exception();
149
    }
150
    if (name)
151
        getMetadataPtr()->setName(name);
152
    else
153
        getMetadataPtr()->setName("");
154
}
155

156
Py::Object MetadataPy::getVersion() const
157
{
158
    return Py::String(getMetadataPtr()->version().str());
159
}
160

161
void MetadataPy::setVersion(Py::Object args)
162
{
163
    const char *name = nullptr;
164
    if (!PyArg_Parse(args.ptr(), "z", &name))
165
        throw Py::Exception();
166
    if (name && name[0] != '\0')
167
        getMetadataPtr()->setVersion(App::Meta::Version(std::string(name)));
168
    else
169
        getMetadataPtr()->setVersion(App::Meta::Version());
170
}
171

172
Py::Object MetadataPy::getDate() const
173
{
174
    return Py::String(getMetadataPtr()->date());
175
}
176

177
void MetadataPy::setDate(Py::Object args)
178
{
179
    const char *date = nullptr;
180
    if (!PyArg_Parse(args.ptr(), "z", &date))
181
        throw Py::Exception();
182
    if (date) getMetadataPtr()->setDate(date);
183
    else
184
        getMetadataPtr()->setDate("");
185
}
186

187
Py::Object MetadataPy::getDescription() const
188
{
189
    return Py::String(getMetadataPtr()->description());
190
}
191

192
void MetadataPy::setDescription(Py::Object args)
193
{
194
    const char *description = nullptr;
195
    if (!PyArg_Parse(args.ptr(), "s", &description))
196
        throw Py::Exception();
197
    getMetadataPtr()->setDescription(description);
198
}
199

200
Py::Object MetadataPy::getType() const
201
{
202
    return Py::String(getMetadataPtr()->type());
203
}
204

205
void MetadataPy::setType(Py::Object args)
206
{
207
    const char *type = nullptr;
208
    if (!PyArg_Parse(args.ptr(), "s", &type))
209
        throw Py::Exception();
210
    getMetadataPtr()->setType(type);
211
}
212

213
Py::Object MetadataPy::getMaintainer() const
214
{
215
    auto maintainers = getMetadataPtr()->maintainer();
216
    Py::List pyMaintainers;
217
    for (const auto &m : maintainers) {
218
        Py::Dict pyMaintainer;
219
        pyMaintainer["name"] = Py::String(m.name);
220
        pyMaintainer["email"] = Py::String(m.email);
221
        pyMaintainers.append(pyMaintainer);
222
    }
223
    return pyMaintainers;
224
}
225

226
void MetadataPy::setMaintainer(Py::Object args)
227
{
228
    PyObject *list = nullptr;
229
    if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list))
230
        throw Py::Exception();
231

232
    getMetadataPtr()->clearMaintainer();
233
    Py::List maintainers(list);
234
    for (const auto &m : maintainers) {
235
        Py::Dict pyMaintainer(m);
236
        std::string name = pyMaintainer["name"].str();
237
        std::string email = pyMaintainer["email"].str();
238
        getMetadataPtr()->addMaintainer(App::Meta::Contact(name, email));
239
    }
240
}
241

242
PyObject *MetadataPy::addMaintainer(PyObject *args)
243
{
244
    const char *name = nullptr;
245
    const char *email = nullptr;
246
    if (!PyArg_ParseTuple(args, "ss", &name, &email))
247
        throw Py::Exception();
248
    getMetadataPtr()->addMaintainer(App::Meta::Contact(name, email));
249
    Py_INCREF(Py_None);
250
    return Py_None;
251
}
252

253
PyObject *MetadataPy::removeMaintainer(PyObject *args)
254
{
255
    const char *name = nullptr;
256
    const char *email = nullptr;
257
    if (!PyArg_ParseTuple(args, "ss", &name, &email))
258
        throw Py::Exception();
259
    getMetadataPtr()->removeMaintainer(App::Meta::Contact(name, email));
260
    Py_INCREF(Py_None);
261
    return Py_None;
262
}
263

264

265
Py::Object MetadataPy::getAuthor() const
266
{
267
    auto authors = getMetadataPtr()->author();
268
    Py::List pyAuthors;
269
    for (const auto &a : authors) {
270
        Py::Dict pyAuthor;
271
        pyAuthor["name"] = Py::String(a.name);
272
        pyAuthor["email"] = Py::String(a.email);
273
        pyAuthors.append(pyAuthor);
274
    }
275
    return pyAuthors;
276
}
277

278
void MetadataPy::setAuthor(Py::Object args)
279
{
280
    PyObject *list = nullptr;
281
    if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list))
282
        throw Py::Exception();
283

284
    getMetadataPtr()->clearAuthor();
285
    Py::List authors(list);
286
    for (const auto &a : authors) {
287
        Py::Dict pyAuthor(a);
288
        std::string name = pyAuthor["name"].str();
289
        std::string email = pyAuthor["email"].str();
290
        getMetadataPtr()->addAuthor(App::Meta::Contact(name, email));
291
    }
292
}
293

294
PyObject *MetadataPy::addAuthor(PyObject *args)
295
{
296
    const char *name = nullptr;
297
    const char *email = nullptr;
298
    if (!PyArg_ParseTuple(args, "ss", &name, &email))
299
        throw Py::Exception();
300
    getMetadataPtr()->addAuthor(App::Meta::Contact(name, email));
301
    Py_INCREF(Py_None);
302
    return Py_None;
303
}
304

305
PyObject *MetadataPy::removeAuthor(PyObject *args)
306
{
307
    const char *name = nullptr;
308
    const char *email = nullptr;
309
    if (!PyArg_ParseTuple(args, "ss", &name, &email))
310
        throw Py::Exception();
311
    getMetadataPtr()->removeAuthor(App::Meta::Contact(name, email));
312
    Py_INCREF(Py_None);
313
    return Py_None;
314
}
315

316
Py::Object MetadataPy::getLicense() const
317
{
318
    auto licenses = getMetadataPtr()->license();
319
    Py::List pyLicenses;
320
    for (const auto &lic : licenses) {
321
        Py::Dict pyLicense;
322
        pyLicense["name"] = Py::String(lic.name);
323
        pyLicense["file"] = Py::String(lic.file.string());
324
        pyLicenses.append(pyLicense);
325
    }
326
    return pyLicenses;
327
}
328

329
void MetadataPy::setLicense(Py::Object args)
330
{
331
    PyObject *list = nullptr;
332
    if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list))
333
        throw Py::Exception();
334

335
    getMetadataPtr()->clearLicense();
336
    Py::List licenses(list);
337
    for (const auto &l : licenses) {
338
        Py::Dict pyLicense(l);
339
        std::string name = pyLicense["name"].str();
340
        std::string path = pyLicense["file"].str();
341
        getMetadataPtr()->addLicense(App::Meta::License(name, path));
342
    }
343
}
344

345
PyObject *MetadataPy::addLicense(PyObject *args)
346
{
347
    const char *shortCode = nullptr;
348
    const char *path = nullptr;
349
    if (!PyArg_ParseTuple(args, "ss", &shortCode, &path))
350
        throw Py::Exception();
351
    getMetadataPtr()->addLicense(App::Meta::License(shortCode, path));
352
    Py_INCREF(Py_None);
353
    return Py_None;
354
}
355

356
PyObject *MetadataPy::removeLicense(PyObject *args)
357
{
358
    const char *shortCode = nullptr;
359
    const char *path = nullptr;
360
    if (!PyArg_ParseTuple(args, "ss", &shortCode, &path))
361
        throw Py::Exception();
362
    getMetadataPtr()->removeLicense(App::Meta::License(shortCode, path));
363
    Py_INCREF(Py_None);
364
    return Py_None;
365
}
366

367
Py::Object MetadataPy::getUrls() const
368
{
369
    auto urls = getMetadataPtr()->url();
370
    Py::List pyUrls;
371
    for (const auto &url : urls) {
372
        Py::Dict pyUrl;
373
        pyUrl["location"] = Py::String(url.location);
374
        switch (url.type) {
375
            case Meta::UrlType::website: pyUrl["type"] = Py::String("website"); break;
376
            case Meta::UrlType::repository: pyUrl["type"] = Py::String("repository"); break;
377
            case Meta::UrlType::bugtracker: pyUrl["type"] = Py::String("bugtracker"); break;
378
            case Meta::UrlType::readme: pyUrl["type"] = Py::String("readme"); break;
379
            case Meta::UrlType::documentation: pyUrl["type"] = Py::String("documentation"); break;
380
            case Meta::UrlType::discussion: pyUrl["type"] = Py::String("discussion"); break;
381
            default: pyUrl["type"] = Py::String("unknown"); break;
382
        }
383
        if (url.type == Meta::UrlType::repository)
384
            pyUrl["branch"] = Py::String(url.branch);
385
        pyUrls.append(pyUrl);
386
    }
387
    return pyUrls;
388
}
389

390
void MetadataPy::setUrls(Py::Object args)
391
{
392
    PyObject *list = nullptr;
393
    if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list))
394
        throw Py::Exception();
395

396
    getMetadataPtr()->clearUrl();
397
    Py::List urls(list);
398
    for (const auto &url : urls) {
399
        Py::Dict pyUrl(url);
400
        std::string location = pyUrl["location"].str();
401
        std::string typeAsString = pyUrl["type"].str();
402
        std::string branch = pyUrl["branch"].str();
403
        auto newUrl = App::Meta::Url(location, Meta::UrlType::website);
404
        if (typeAsString == "website") {
405
            newUrl.type = Meta::UrlType::website;
406
        }
407
        else if (typeAsString == "repository") {
408
            newUrl.type = Meta::UrlType::repository;
409
            newUrl.branch = branch;
410
        }
411
        else if (typeAsString == "bugtracker") {
412
            newUrl.type = Meta::UrlType::bugtracker;
413
        }
414
        else if (typeAsString == "readme") {
415
            newUrl.type = Meta::UrlType::readme;
416
        }
417
        else if (typeAsString == "documentation") {
418
            newUrl.type = Meta::UrlType::documentation;
419
        }
420
        else if (typeAsString == "discussion") {
421
            newUrl.type = Meta::UrlType::discussion;
422
        }
423
        else {
424
            PyErr_SetString(Base::PyExc_FC_GeneralError, "Unrecognized URL type");
425
            return;
426
        }
427
        getMetadataPtr()->addUrl(newUrl);
428
    }
429
}
430

431
App::Meta::Url urlFromStrings(const char* urlTypeCharStar, const char* link, const char* branch)
432
{
433
    std::string urlTypeString(urlTypeCharStar);
434
    App::Meta::UrlType urlType{App::Meta::UrlType::documentation};
435
    if (urlTypeString == "repository")
436
        urlType = App::Meta::UrlType::repository;
437
    else if (urlTypeString == "bugtracker")
438
        urlType = App::Meta::UrlType::bugtracker;
439
    else if (urlTypeString == "documentation")
440
        urlType = App::Meta::UrlType::documentation;
441
    else if (urlTypeString == "readme")
442
        urlType = App::Meta::UrlType::readme;
443
    else if (urlTypeString == "website")
444
        urlType = App::Meta::UrlType::website;
445

446
    App::Meta::Url url(link, urlType);
447
    if (urlType == App::Meta::UrlType::repository)
448
        url.branch = std::string(branch);
449

450
    return url;
451
}
452

453
PyObject *MetadataPy::addUrl(PyObject *args)
454
{
455
    const char *urlTypeCharStar = nullptr;
456
    const char *link = nullptr;
457
    const char *branch = nullptr;
458
    if (!PyArg_ParseTuple(args, "ss|s", &urlTypeCharStar, &link, &branch))
459
        throw Py::Exception();
460

461
    getMetadataPtr()->addUrl(urlFromStrings(urlTypeCharStar, link, branch));
462
    Py_INCREF(Py_None);
463
    return Py_None;
464
}
465

466
PyObject *MetadataPy::removeUrl(PyObject *args)
467
{
468
    const char *urlTypeCharStar = nullptr;
469
    const char *link = nullptr;
470
    const char *branch = nullptr;
471
    if (!PyArg_ParseTuple(args, "ss|s", &urlTypeCharStar, &link, &branch))
472
        throw Py::Exception();
473

474
    getMetadataPtr()->removeUrl(urlFromStrings(urlTypeCharStar, link, branch));
475
    Py_INCREF(Py_None);
476
    return Py_None;
477
}
478

479
Py::Object dependencyToPyObject(const Meta::Dependency &d)
480
{
481
    Py::Dict pyDependency;
482
    pyDependency["package"] = Py::String(d.package);
483
    pyDependency["version_lt"] = Py::String(d.version_lt);
484
    pyDependency["version_lte"] = Py::String(d.version_lte);
485
    pyDependency["version_eq"] = Py::String(d.version_eq);
486
    pyDependency["version_gt"] = Py::String(d.version_gt);
487
    pyDependency["version_gte"] = Py::String(d.version_gte);
488
    pyDependency["condition"] = Py::String(d.condition);
489
    pyDependency["optional"] = Py::Boolean(d.optional);
490
    switch (d.dependencyType) {
491
        case App::Meta::DependencyType::automatic:
492
            pyDependency["type"] = Py::String ("automatic");
493
            break;
494
        case App::Meta::DependencyType::addon:
495
            pyDependency["type"] = Py::String("addon");
496
            break;
497
        case App::Meta::DependencyType::internal:
498
            pyDependency["type"] = Py::String("internal");
499
            break;
500
        case App::Meta::DependencyType::python:
501
            pyDependency["type"] = Py::String("python");
502
            break;
503
    }
504
    return pyDependency;
505
}
506

507
Meta::Dependency pyObjectToDependency(const Py::Object &d)
508
{
509
    Py::Dict pyDependency(d);
510
    Meta::Dependency result;
511
    result.package = pyDependency["package"].str();
512
    if (pyDependency.hasKey("version_lt"))
513
        result.version_lt = pyDependency["version_lt"].str();
514
    if (pyDependency.hasKey("version_lte"))
515
        result.version_lte = pyDependency["version_lte"].str();
516
    if (pyDependency.hasKey("version_eq"))
517
        result.version_eq = pyDependency["version_eq"].str();
518
    if (pyDependency.hasKey("version_gt"))
519
        result.version_gt = pyDependency["version_gt"].str();
520
    if (pyDependency.hasKey("version_gte"))
521
        result.version_gte = pyDependency["version_gte"].str();
522
    if (pyDependency.hasKey("condition"))
523
        result.condition = pyDependency["condition"].str();
524
    if (pyDependency.hasKey("optional"))
525
        result.optional = Py::Boolean(pyDependency["optional"]).as_bool();
526
    if (pyDependency.hasKey("type")) {
527
        if (pyDependency["type"].str() == Py::String("automatic"))
528
            result.dependencyType = App::Meta::DependencyType::automatic;
529
        else if (pyDependency["type"].str() == Py::String("internal"))
530
            result.dependencyType = App::Meta::DependencyType::internal;
531
        else if (pyDependency["type"].str() == Py::String("addon"))
532
            result.dependencyType = App::Meta::DependencyType::addon;
533
        else if (pyDependency["type"].str() == Py::String("python"))
534
            result.dependencyType = App::Meta::DependencyType::python;
535
    }
536
    return result;
537
}
538

539
Py::Object MetadataPy::getDepend() const
540
{
541
    auto dependencies = getMetadataPtr()->depend();
542
    Py::List pyDependencies;
543
    for (const auto &d : dependencies) {
544
        pyDependencies.append(dependencyToPyObject(d));
545
    }
546
    return pyDependencies;
547
}
548

549
void MetadataPy::setDepend(Py::Object args)
550
{
551
    PyObject *list = nullptr;
552
    if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list))
553
        throw Py::Exception();
554

555
    getMetadataPtr()->clearDepend();
556
    Py::List deps(list);
557
    for (const auto &dep : deps) {
558
        Py::Dict pyDep(dep);
559
        getMetadataPtr()->addDepend(pyObjectToDependency(pyDep));
560
    }
561
}
562

563
PyObject *MetadataPy::addDepend(PyObject *args)
564
{
565
    PyObject *dictionary = nullptr;
566
    if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary))
567
        throw Py::Exception();
568
    Py::Dict pyDep(dictionary);
569
    getMetadataPtr()->addDepend(pyObjectToDependency(pyDep));
570
    Py_INCREF(Py_None);
571
    return Py_None;
572
}
573

574
PyObject *MetadataPy::removeDepend(PyObject *args)
575
{
576
    PyObject *dictionary = nullptr;
577
    if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary))
578
        throw Py::Exception();
579
    Py::Dict pyDep(dictionary);
580
    getMetadataPtr()->removeDepend(pyObjectToDependency(pyDep));
581
    Py_INCREF(Py_None);
582
    return Py_None;
583
}
584

585
Py::Object MetadataPy::getConflict() const
586
{
587
    auto dependencies = getMetadataPtr()->conflict();
588
    Py::List pyDependencies;
589
    for (const auto &d : dependencies) {
590
        pyDependencies.append(dependencyToPyObject(d));
591
    }
592
    return pyDependencies;
593
}
594

595
void MetadataPy::setConflict(Py::Object args)
596
{
597
    PyObject *list = nullptr;
598
    if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list))
599
        throw Py::Exception();
600

601
    getMetadataPtr()->clearConflict();
602
    Py::List deps(list);
603
    for (const auto &dep : deps) {
604
        Py::Dict pyDep(dep);
605
        getMetadataPtr()->addConflict(pyObjectToDependency(pyDep));
606
    }
607
}
608

609
PyObject *MetadataPy::addConflict(PyObject *args)
610
{
611
    PyObject *dictionary = nullptr;
612
    if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary))
613
        throw Py::Exception();
614
    Py::Dict pyDep(dictionary);
615
    getMetadataPtr()->addConflict(pyObjectToDependency(pyDep));
616
    Py_INCREF(Py_None);
617
    return Py_None;
618
}
619

620
PyObject *MetadataPy::removeConflict(PyObject *args)
621
{
622
    PyObject *dictionary = nullptr;
623
    if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary))
624
        throw Py::Exception();
625
    Py::Dict pyDep(dictionary);
626
    getMetadataPtr()->removeConflict(pyObjectToDependency(pyDep));
627
    Py_INCREF(Py_None);
628
    return Py_None;
629
}
630

631
Py::Object MetadataPy::getReplace() const
632
{
633
    auto dependencies = getMetadataPtr()->replace();
634
    Py::List pyDependencies;
635
    for (const auto &d : dependencies) {
636
        pyDependencies.append(dependencyToPyObject(d));
637
    }
638
    return pyDependencies;
639
}
640

641
void MetadataPy::setReplace(Py::Object args)
642
{
643
    PyObject *list = nullptr;
644
    if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list))
645
        throw Py::Exception();
646

647
    getMetadataPtr()->clearReplace();
648
    Py::List deps(list);
649
    for (const auto &dep : deps) {
650
        Py::Dict pyDep(dep);
651
        getMetadataPtr()->addReplace(pyObjectToDependency(pyDep));
652
    }
653
}
654

655
PyObject *MetadataPy::addReplace(PyObject *args)
656
{
657
    PyObject *dictionary = nullptr;
658
    if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary))
659
        throw Py::Exception();
660
    Py::Dict pyDep(dictionary);
661
    getMetadataPtr()->addReplace(pyObjectToDependency(pyDep));
662
    Py_INCREF(Py_None);
663
    return Py_None;
664
}
665

666
PyObject *MetadataPy::removeReplace(PyObject *args)
667
{
668
    PyObject *dictionary = nullptr;
669
    if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dictionary))
670
        throw Py::Exception();
671
    Py::Dict pyDep(dictionary);
672
    getMetadataPtr()->removeReplace(pyObjectToDependency(pyDep));
673
    Py_INCREF(Py_None);
674
    return Py_None;
675
}
676

677
// Tag, icon, classname, file
678

679
Py::Object MetadataPy::getTag() const
680
{
681
    auto tags = getMetadataPtr()->tag();
682
    Py::List pyTags;
683
    for (const auto &t : tags) {
684
        pyTags.append(Py::String(t));
685
    }
686
    return pyTags;
687
}
688

689
void MetadataPy::setTag(Py::Object args)
690
{
691
    PyObject *list = nullptr;
692
    if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list))
693
        throw Py::Exception();
694

695
    getMetadataPtr()->clearTag();
696
    Py::List tags(list);
697
    for (const auto &tag : tags) {
698
        Py::String pyTag(tag);
699
        getMetadataPtr()->addTag(pyTag.as_std_string());
700
    }
701
}
702

703
PyObject *MetadataPy::addTag(PyObject *args)
704
{
705
    const char *tag = nullptr;
706
    if (!PyArg_ParseTuple(args, "s", &tag))
707
        throw Py::Exception();
708
    getMetadataPtr()->addTag(tag);
709
    Py_INCREF(Py_None);
710
    return Py_None;
711
}
712

713
PyObject *MetadataPy::removeTag(PyObject *args)
714
{
715
    const char *tag = nullptr;
716
    if (!PyArg_ParseTuple(args, "s", &tag))
717
        throw Py::Exception();
718
    getMetadataPtr()->removeTag(tag);
719
    Py_INCREF(Py_None);
720
    return Py_None;
721
}
722

723
Py::Object MetadataPy::getIcon() const
724
{
725
    return Py::String(getMetadataPtr()->icon().string());
726
}
727

728
void MetadataPy::setIcon(Py::Object args)
729
{
730
    const char *name;
731
    if (!PyArg_Parse(args.ptr(), "s", &name))
732
        throw Py::Exception();
733
    getMetadataPtr()->setIcon(name);
734
}
735

736
Py::Object MetadataPy::getClassname() const
737
{
738
    return Py::String(getMetadataPtr()->classname());
739
}
740

741
void MetadataPy::setClassname(Py::Object args)
742
{
743
    const char *name;
744
    if (!PyArg_Parse(args.ptr(), "s", &name))
745
        throw Py::Exception();
746
    getMetadataPtr()->setClassname(name);
747
}
748

749
Py::Object MetadataPy::getSubdirectory() const
750
{
751
    return Py::String(getMetadataPtr()->subdirectory().string());
752
}
753

754
void MetadataPy::setSubdirectory(Py::Object args)
755
{
756
    const char *name;
757
    if (!PyArg_Parse(args.ptr(), "s", &name))
758
        throw Py::Exception();
759
    getMetadataPtr()->setSubdirectory(name);
760
}
761

762
Py::Object MetadataPy::getFile() const
763
{
764
    auto files = getMetadataPtr()->file();
765
    Py::List pyFiles;
766
    for (const auto &f : files) {
767
        pyFiles.append(Py::String(f.string()));
768
    }
769
    return pyFiles;
770
}
771

772
void MetadataPy::setFile(Py::Object args)
773
{
774
    PyObject *list = nullptr;
775
    if (!PyArg_Parse(args.ptr(), "O!", &PyList_Type, &list))
776
        throw Py::Exception();
777

778
    getMetadataPtr()->clearTag();
779
    Py::List files(list);
780
    for (const auto &file : files) {
781
        Py::String pyFile(file);
782
        getMetadataPtr()->addFile(pyFile.as_std_string());
783
    }
784
}
785

786
PyObject *MetadataPy::addFile(PyObject *args)
787
{
788
    const char *file = nullptr;
789
    if (!PyArg_ParseTuple(args, "s", &file))
790
        throw Py::Exception();
791
    getMetadataPtr()->addFile(file);
792
    Py_INCREF(Py_None);
793
    return Py_None;
794
}
795

796
PyObject *MetadataPy::removeFile(PyObject *args)
797
{
798
    const char *file = nullptr;
799
    if (!PyArg_ParseTuple(args, "s", &file))
800
        throw Py::Exception();
801
    getMetadataPtr()->removeFile(file);
802
    Py_INCREF(Py_None);
803
    return Py_None;
804
}
805

806

807
Py::Object MetadataPy::getContent() const
808
{
809
    auto content = getMetadataPtr()->content();
810
    std::set<std::string> keys;
811
    for (const auto &item : content) {
812
        keys.insert(item.first);
813
    }
814

815
    // For the Python, we'll use a dictionary of lists to store the content components:
816
    Py::Dict pyContent;
817
    for (const auto &key : keys) {
818
        Py::List pyContentForKey;
819
        auto elements = content.equal_range(key);
820
        for (auto &element = elements.first; element != elements.second; ++element) {
821
            auto contentMetadataItem = new MetadataPy(new Metadata(element->second));
822
            pyContentForKey.append(Py::asObject(contentMetadataItem));
823
        }
824
        pyContent[key] = pyContentForKey;
825
    }
826
    return pyContent;
827
}
828

829
void MetadataPy::setContent(Py::Object arg)
830
{
831
    PyObject *obj = nullptr;
832
    if (!PyArg_Parse(arg.ptr(), "O!", &PyList_Type, &obj))
833
        throw Py::Exception();
834

835
    getMetadataPtr()->clearContent();
836
    Py::Dict outerDict(obj);
837
    for (const auto &pyContentType : outerDict) {
838
        auto contentType = Py::String(pyContentType.first).as_std_string();
839
        auto contentList = Py::List(pyContentType.second);
840
        for (const auto& contentItem : contentList) {
841
            auto item = static_cast<MetadataPy *>(contentItem.ptr());
842
            getMetadataPtr()->addContentItem(contentType, *(item->getMetadataPtr()));
843
        }
844
    }
845

846
}
847

848
PyObject *MetadataPy::getGenericMetadata(PyObject *args)
849
{
850
    const char *name;
851
    if (!PyArg_ParseTuple(args, "s", &name))
852
        return nullptr;
853

854
    auto gm = (*getMetadataPtr())[name];
855
    Py::List pyGenericMetadata;
856
    for (const auto &item : gm) {
857
        Py::Dict pyItem;
858
        pyItem["contents"] = Py::String(item.contents);
859
        Py::Dict pyAttributes;
860
        for (const auto &attribute : item.attributes) {
861
            pyAttributes[attribute.first] = Py::String(attribute.second);
862
        }
863
        pyItem["attributes"] = pyAttributes;
864
        pyGenericMetadata.append(pyItem);
865
    }
866
    return Py::new_reference_to(pyGenericMetadata);
867
}
868

869
Py::Object MetadataPy::getFreeCADMin() const
870
{
871
    return Py::String(getMetadataPtr()->freecadmin().str());
872
}
873

874
void MetadataPy::setFreeCADMin(Py::Object args)
875
{
876
    char *version = nullptr;
877
    PyObject *p = args.ptr();
878
    if (!PyArg_Parse(p, "z", &version))
879
        throw Py::Exception();
880
    if (version)
881
        getMetadataPtr()->setFreeCADMin(App::Meta::Version(version));
882
    else
883
        getMetadataPtr()->setFreeCADMin(App::Meta::Version());
884
}
885

886
Py::Object MetadataPy::getFreeCADMax() const
887
{
888
    return Py::String(getMetadataPtr()->freecadmax().str());
889
}
890

891
void MetadataPy::setFreeCADMax(Py::Object args)
892
{
893
    char *version = nullptr;
894
    PyObject *p = args.ptr();
895
    if (!PyArg_Parse(p, "z", &version))
896
        throw Py::Exception();
897

898
    if (version)
899
        getMetadataPtr()->setFreeCADMax(App::Meta::Version(version));
900
    else
901
        getMetadataPtr()->setFreeCADMax(App::Meta::Version());
902
}
903

904
Py::Object MetadataPy::getPythonMin() const
905
{
906
    return Py::String(getMetadataPtr()->pythonmin().str());
907
}
908

909
void MetadataPy::setPythonMin(Py::Object args)
910
{
911
    char *version = nullptr;
912
    PyObject *p = args.ptr();
913
    if (!PyArg_Parse(p, "z", &version)) throw Py::Exception();
914
    if (version) getMetadataPtr()->setPythonMin(App::Meta::Version(version));
915
    else
916
        getMetadataPtr()->setPythonMin(App::Meta::Version());
917
}
918

919
PyObject *MetadataPy::getFirstSupportedFreeCADVersion(PyObject *p)
920
{
921
    if (!PyArg_ParseTuple(p, ""))
922
        return nullptr;
923

924
    // Short-circuit: if the toplevel sets a version, then the lower-levels are overridden
925
    if (getMetadataPtr()->freecadmin() != App::Meta::Version())
926
        return Py::new_reference_to(Py::String(getMetadataPtr()->freecadmin().str()));
927

928
    auto content = getMetadataPtr()->content();
929
    auto result = App::Meta::Version();
930
    for (const auto &item : content) {
931
        auto minVersion = item.second.freecadmin();
932
        if (minVersion != App::Meta::Version())
933
            if (result == App::Meta::Version() || minVersion < result)
934
                result = minVersion;
935
    }
936
    if (result != App::Meta::Version()) {
937
        return Py::new_reference_to(Py::String(result.str()));
938
    }
939
    else {
940
        Py_INCREF(Py_None);
941
        return Py_None;
942
    }
943
}
944

945
PyObject *MetadataPy::getLastSupportedFreeCADVersion(PyObject *p)
946
{
947
    if (!PyArg_ParseTuple(p, ""))
948
        return nullptr;
949

950
    // Short-circuit: if the toplevel sets a version, then the lower-levels are overridden
951
    if (getMetadataPtr()->freecadmax() != App::Meta::Version())
952
        return Py::new_reference_to(Py::String(getMetadataPtr()->freecadmax().str()));
953

954
    auto content = getMetadataPtr()->content();
955
    auto result = App::Meta::Version();
956
    for (const auto &item : content) {
957
        auto maxVersion = item.second.freecadmax();
958
        if (maxVersion != App::Meta::Version())
959
            if (result == App::Meta::Version() || maxVersion > result)
960
                result = maxVersion;
961
    }
962
    if (result != App::Meta::Version()) {
963
        return Py::new_reference_to(Py::String(result.str()));
964
    }
965
    else {
966
        Py_INCREF(Py_None);
967
        return Py_None;
968
    }
969
}
970

971
PyObject *MetadataPy::supportsCurrentFreeCAD(PyObject *p)
972
{
973
    if (!PyArg_ParseTuple(p, ""))
974
        return nullptr;
975

976
    bool result = getMetadataPtr()->supportsCurrentFreeCAD();
977
    return Py::new_reference_to(Py::Boolean(result));
978
}
979

980
PyObject* MetadataPy::addContentItem(PyObject* arg)
981
{
982
    char *contentType = nullptr;
983
    PyObject *contentItem = nullptr;
984
    if (!PyArg_ParseTuple(arg, "sO!", &contentType, &(App::MetadataPy::Type), &contentItem))
985
        return nullptr;
986

987
    if (!contentItem || !contentType)
988
        return nullptr;
989
    auto item = static_cast<MetadataPy *>(contentItem);
990
    getMetadataPtr()->addContentItem(contentType, *(item->getMetadataPtr()));
991

992
    Py_INCREF(Py_None);
993
    return Py_None;
994
}
995

996
PyObject *MetadataPy::removeContentItem(PyObject *arg)
997
{
998
    char *contentType = nullptr;
999
    char *contentName = nullptr;
1000
    if (!PyArg_ParseTuple(arg, "ss", &contentType, &contentName))
1001
        return nullptr;
1002
    if (contentType && contentName)
1003
        getMetadataPtr()->removeContentItem(contentType, contentName);
1004

1005
    Py_INCREF(Py_None);
1006
    return Py_None;
1007
}
1008

1009
PyObject* MetadataPy::write(PyObject* args)
1010
{
1011
    char *filename = nullptr;
1012
    if (!PyArg_ParseTuple(args, "s", &filename))
1013
        return nullptr;
1014
    getMetadataPtr()->write(filename);
1015

1016
    Py_INCREF(Py_None);
1017
    return Py_None;
1018
}
1019

1020

1021
PyObject *MetadataPy::getCustomAttributes(const char * /*attr*/) const
1022
{
1023
    return nullptr;
1024
}
1025

1026
int MetadataPy::setCustomAttributes(const char * /*attr*/, PyObject * /*obj*/)
1027
{
1028
    return 0;
1029
}
1030

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.