mirror of
https://github.com/loot/libloot-python.git
synced 2026-07-27 14:14:13 -07:00
Update to LOOT API v0.11.0
This is a breaking change: - LanguageCode has been removed - The SimpleMessage Python class is now "SimpleMessage", from "Message" - DatabaseInterface::sort_plugins() has been removed - DatabaseInterface::get_plugin_messages() has been replaced with DatabaseInterface::get_plugin_metadata() followed by PluginMetadata::get_simple_messages() - set_logging_verbosity(), set_log_file() and initialise_locale() have been added Not everything in the v0.11 API has been wrapped, to limit the potential for future breaking changes. The PluginTags struct and PluginCleanliness enum and their associated functions have been re-implemented as part of the Python wrapper as they were removed from the API due to no longer exposing any additional functionality but are still useful.
This commit is contained in:
+4
-2
@@ -51,7 +51,7 @@ add_subdirectory(${PYBIND11_EXTRACTED_PATH})
|
||||
|
||||
ExternalProject_Add(loot-api-c++
|
||||
PREFIX "external"
|
||||
URL "https://github.com/loot/loot/releases/download/0.10.2/loot-api_0.10.2-0-g9eb7d26_dev.7z"
|
||||
URL "https://github.com/loot/loot-api/releases/download/0.11.0/loot_api-0.11.0-0-g8864f78_dev-win32.7z"
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND "")
|
||||
@@ -79,7 +79,9 @@ ExternalProject_Add(test-masterlist
|
||||
# Python Module
|
||||
#######################################
|
||||
|
||||
pybind11_add_module(loot_api "${CMAKE_SOURCE_DIR}/src/main.cpp" "${CMAKE_BINARY_DIR}/generated/wrapper_version.cpp")
|
||||
pybind11_add_module(loot_api "${CMAKE_SOURCE_DIR}/src/main.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/convenience.cpp"
|
||||
"${CMAKE_BINARY_DIR}/generated/wrapper_version.cpp")
|
||||
|
||||
add_dependencies(loot_api loot-api-c++ test-masterlist)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ LOOT API Python Module
|
||||
[](https://travis-ci.org/loot/loot-api-python)
|
||||
[](http://loot-api-python.readthedocs.io/)
|
||||
|
||||
A Python module that wraps the LOOT API, generated by [pybind11](https://github.com/pybind/pybind11).
|
||||
A Python module that wraps the LOOT API, generated by [pybind11](https://github.com/pybind/pybind11). Not everything in the API is exposed: coverage can be extended on request (or by pull request).
|
||||
|
||||
## Downloads
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2017 Oliver Hamlet
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "convenience.h"
|
||||
|
||||
#include <loot/api.h>
|
||||
|
||||
namespace loot {
|
||||
std::shared_ptr<DatabaseInterface> CreateDatabase(const GameType game, const std::string & game_path, const std::string & game_local_path) {
|
||||
auto gameHandle = CreateGameHandle(game, game_path, game_local_path);
|
||||
|
||||
return gameHandle->GetDatabase();
|
||||
}
|
||||
PluginTags GetPluginTags(const std::shared_ptr<DatabaseInterface> db, const std::string& plugin) {
|
||||
PluginTags tags;
|
||||
|
||||
auto metadata = db->GetPluginMetadata(plugin, false, false);
|
||||
for (const auto &tag : metadata.GetTags()) {
|
||||
if (tag.IsAddition())
|
||||
tags.added.insert(tag.GetName());
|
||||
else
|
||||
tags.removed.insert(tag.GetName());
|
||||
}
|
||||
|
||||
metadata = db->GetPluginUserMetadata(plugin, false);
|
||||
tags.userlist_modified = !metadata.GetTags().empty();
|
||||
for (const auto &tag : metadata.GetTags()) {
|
||||
if (tag.IsAddition())
|
||||
tags.added.insert(tag.GetName());
|
||||
else
|
||||
tags.removed.insert(tag.GetName());
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
PluginCleanliness GetPluginCleanliness(const std::shared_ptr<DatabaseInterface> db, const std::string& plugin) {
|
||||
auto metadata = db->GetPluginMetadata(plugin, true, false);
|
||||
|
||||
if (metadata.GetDirtyInfo().empty()) {
|
||||
if (metadata.GetCleanInfo().empty()) {
|
||||
return PluginCleanliness::unknown;
|
||||
} else {
|
||||
return PluginCleanliness::clean;
|
||||
}
|
||||
} else if (!metadata.GetCleanInfo().empty()) {
|
||||
return PluginCleanliness::unknown;
|
||||
}
|
||||
|
||||
for (const auto& info : metadata.GetDirtyInfo()) {
|
||||
if (info.ChooseInfo("en").GetText().find("Do not clean") != std::string::npos) {
|
||||
return PluginCleanliness::do_not_clean;
|
||||
}
|
||||
}
|
||||
|
||||
return PluginCleanliness::unknown;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2014-2017 Oliver Hamlet
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_API_PYTHON_CONVENIENCE
|
||||
#define LOOT_API_PYTHON_CONVENIENCE
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <loot/enum/game_type.h>
|
||||
#include <loot/database_interface.h>
|
||||
|
||||
#include "plugin_cleanliness.h"
|
||||
#include "plugin_tags.h"
|
||||
|
||||
namespace loot {
|
||||
std::shared_ptr<DatabaseInterface> CreateDatabase(const GameType game,
|
||||
const std::string& game_path = "",
|
||||
const std::string& game_local_path = "");
|
||||
|
||||
PluginTags GetPluginTags(const std::shared_ptr<DatabaseInterface> db, const std::string& plugin);
|
||||
|
||||
PluginCleanliness GetPluginCleanliness(const std::shared_ptr<DatabaseInterface> db, const std::string& plugin);
|
||||
}
|
||||
|
||||
#endif
|
||||
+50
-37
@@ -26,29 +26,16 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/stl.h>
|
||||
|
||||
#include "convenience.h"
|
||||
#include "wrapper_version.h"
|
||||
|
||||
PYBIND11_PLUGIN(loot_api) {
|
||||
using loot::CreateDatabase;
|
||||
using loot::DatabaseInterface;
|
||||
using loot::IsCompatible;
|
||||
using loot::GameType;
|
||||
using loot::LanguageCode;
|
||||
using loot::LootVersion;
|
||||
using loot::MessageType;
|
||||
using loot::MasterlistInfo;
|
||||
using loot::PluginCleanliness;
|
||||
using loot::SimpleMessage;
|
||||
using loot::PluginTags;
|
||||
using loot::WrapperVersion;
|
||||
|
||||
using pybind11::arg;
|
||||
using pybind11::enum_;
|
||||
using pybind11::class_;
|
||||
using pybind11::metaclass;
|
||||
|
||||
pybind11::module module("loot_api", "A Python module that wraps the LOOT API, generated by pybind11.");
|
||||
using pybind11::arg;
|
||||
using pybind11::enum_;
|
||||
using pybind11::class_;
|
||||
using pybind11::metaclass;
|
||||
|
||||
namespace loot {
|
||||
void bindEnums(pybind11::module& module) {
|
||||
enum_<GameType>(module, "GameType")
|
||||
.value("tes4", GameType::tes4)
|
||||
.value("tes5", GameType::tes5)
|
||||
@@ -57,18 +44,10 @@ PYBIND11_PLUGIN(loot_api) {
|
||||
.value("fonv", GameType::fonv)
|
||||
.value("fo4", GameType::fo4);
|
||||
|
||||
enum_<LanguageCode>(module, "LanguageCode")
|
||||
.value("english", LanguageCode::english)
|
||||
.value("spanish", LanguageCode::spanish)
|
||||
.value("russian", LanguageCode::russian)
|
||||
.value("french", LanguageCode::french)
|
||||
.value("chinese", LanguageCode::chinese)
|
||||
.value("polish", LanguageCode::polish)
|
||||
.value("brazilian_portuguese", LanguageCode::brazilian_portuguese)
|
||||
.value("finnish", LanguageCode::finnish)
|
||||
.value("german", LanguageCode::german)
|
||||
.value("danish", LanguageCode::danish)
|
||||
.value("korean", LanguageCode::korean);
|
||||
enum_<LogVerbosity>(module, "LogVerbosity")
|
||||
.value("off", LogVerbosity::off)
|
||||
.value("trace", LogVerbosity::trace)
|
||||
.value("warning", LogVerbosity::warning);
|
||||
|
||||
enum_<MessageType>(module, "MessageType")
|
||||
.value("say", MessageType::say)
|
||||
@@ -80,13 +59,15 @@ PYBIND11_PLUGIN(loot_api) {
|
||||
.value("dirty", PluginCleanliness::dirty)
|
||||
.value("do_not_clean", PluginCleanliness::do_not_clean)
|
||||
.value("unknown", PluginCleanliness::unknown);
|
||||
}
|
||||
|
||||
void bindMetadataClasses(pybind11::module& module) {
|
||||
class_<MasterlistInfo>(module, "MasterlistInfo")
|
||||
.def_readwrite("revision_id", &MasterlistInfo::revision_id)
|
||||
.def_readwrite("revision_date", &MasterlistInfo::revision_date)
|
||||
.def_readwrite("is_modified", &MasterlistInfo::is_modified);
|
||||
|
||||
class_<SimpleMessage>(module, "Message")
|
||||
class_<SimpleMessage>(module, "SimpleMessage")
|
||||
.def_readwrite("type", &SimpleMessage::type)
|
||||
.def_readwrite("language", &SimpleMessage::language)
|
||||
.def_readwrite("text", &SimpleMessage::text);
|
||||
@@ -96,6 +77,11 @@ PYBIND11_PLUGIN(loot_api) {
|
||||
.def_readwrite("removed", &PluginTags::removed)
|
||||
.def_readwrite("userlist_modified", &PluginTags::userlist_modified);
|
||||
|
||||
class_<PluginMetadata>(module, "PluginMetadata")
|
||||
.def("get_simple_messages", &PluginMetadata::GetSimpleMessages);
|
||||
}
|
||||
|
||||
void bindVersionClasses(pybind11::module& module) {
|
||||
class_<LootVersion>(module, "Version", metaclass())
|
||||
.def_readonly_static("major", &LootVersion::major)
|
||||
.def_readonly_static("minor", &LootVersion::minor)
|
||||
@@ -109,21 +95,48 @@ PYBIND11_PLUGIN(loot_api) {
|
||||
.def_readonly_static("patch", &WrapperVersion::patch)
|
||||
.def_readonly_static("revision", &WrapperVersion::revision)
|
||||
.def_static("string", WrapperVersion::string);
|
||||
}
|
||||
|
||||
void bindInterfaceClasses(pybind11::module& module) {
|
||||
class_<DatabaseInterface, std::shared_ptr<DatabaseInterface>>(module, "DatabaseInterface")
|
||||
.def("load_lists", &DatabaseInterface::LoadLists, arg("masterlist_path"), arg("userlist_path") = "")
|
||||
.def("eval_lists", &DatabaseInterface::EvalLists)
|
||||
.def("sort_plugins", &DatabaseInterface::SortPlugins)
|
||||
.def("update_masterlist", &DatabaseInterface::UpdateMasterlist)
|
||||
.def("get_masterlist_revision", &DatabaseInterface::GetMasterlistRevision)
|
||||
.def("get_plugin_tags", &DatabaseInterface::GetPluginTags)
|
||||
.def("get_plugin_messages", &DatabaseInterface::GetPluginMessages)
|
||||
.def("get_plugin_cleanliness", &DatabaseInterface::GetPluginCleanliness)
|
||||
.def("get_plugin_metadata", &DatabaseInterface::GetPluginMetadata,
|
||||
arg("plugin"),
|
||||
arg("includeUserMetadata") = true,
|
||||
arg("evaluateConditions") = false)
|
||||
.def("get_plugin_tags", &GetPluginTags)
|
||||
.def("get_plugin_cleanliness", &GetPluginCleanliness)
|
||||
.def("write_minimal_list", &DatabaseInterface::WriteMinimalList);
|
||||
}
|
||||
|
||||
void bindClasses(pybind11::module& module) {
|
||||
bindMetadataClasses(module);
|
||||
bindVersionClasses(module);
|
||||
bindInterfaceClasses(module);
|
||||
}
|
||||
|
||||
void bindFunctions(pybind11::module& module) {
|
||||
module.def("set_logging_verbosity", &SetLoggingVerbosity);
|
||||
|
||||
module.def("set_log_file", &SetLogFile);
|
||||
|
||||
module.def("is_compatible", &IsCompatible);
|
||||
|
||||
module.def("initialise_locale", &InitialiseLocale);
|
||||
|
||||
module.def("create_database", &CreateDatabase, arg("game"), arg("game_path") = "", arg("game_local_path") = "");
|
||||
}
|
||||
}
|
||||
|
||||
PYBIND11_PLUGIN(loot_api) {
|
||||
pybind11::module module("loot_api", "A Python module that wraps the LOOT API, generated by pybind11.");
|
||||
|
||||
loot::bindEnums(module);
|
||||
loot::bindClasses(module);
|
||||
loot::bindFunctions(module);
|
||||
|
||||
return module.ptr();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2012-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LOOT_PLUGIN_CLEANLINESS
|
||||
#define LOOT_PLUGIN_CLEANLINESS
|
||||
|
||||
/**
|
||||
* The namespace used by the LOOT API.
|
||||
*/
|
||||
namespace loot {
|
||||
/**
|
||||
* @brief Codes used to indicate the cleanliness of a plugin according to the
|
||||
* information contained within the loaded masterlist/userlist.
|
||||
*/
|
||||
enum struct PluginCleanliness : unsigned int {
|
||||
/** Indicates that the plugin is clean. */
|
||||
clean,
|
||||
/** Indicates that the plugin is dirty. */
|
||||
dirty,
|
||||
/**
|
||||
* Indicates that the plugin contains dirty edits, but that they are
|
||||
* part of the plugin's intended functionality and should not be removed.
|
||||
*/
|
||||
do_not_clean,
|
||||
/**
|
||||
* Indicates that no data is available on whether the plugin is dirty or not.
|
||||
*/
|
||||
unknown,
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,58 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2012-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LOOT_PLUGIN_TAGS
|
||||
#define LOOT_PLUGIN_TAGS
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace loot {
|
||||
/**
|
||||
* @brief A structure that holds data about the Bash Tag suggestions made by
|
||||
* LOOT for a plugin.
|
||||
*/
|
||||
struct PluginTags {
|
||||
inline PluginTags() : userlist_modified(false) {}
|
||||
|
||||
/**
|
||||
* @brief A set of Bash Tag names suggested for addition to the specified
|
||||
* plugin. Empty if no Bash Tag additions are suggested.
|
||||
*/
|
||||
std::set<std::string> added;
|
||||
|
||||
/**
|
||||
* @brief A set of Bash Tag names suggested for removal from the specified
|
||||
* plugin. Empty if no Bash Tag removals are suggested.
|
||||
*/
|
||||
std::set<std::string> removed;
|
||||
|
||||
/**
|
||||
* @brief `true` if the Bash Tag suggestions were modified by data in the
|
||||
* userlist, `false` otherwise.
|
||||
*/
|
||||
bool userlist_modified;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
+12
-15
@@ -7,11 +7,16 @@ import unittest
|
||||
from loot_api import Version
|
||||
from loot_api import WrapperVersion
|
||||
from loot_api import GameType
|
||||
from loot_api import LanguageCode
|
||||
from loot_api import Message
|
||||
from loot_api import LogVerbosity
|
||||
from loot_api import SimpleMessage
|
||||
from loot_api import MessageType
|
||||
from loot_api import create_database
|
||||
from loot_api import is_compatible
|
||||
from loot_api import set_logging_verbosity
|
||||
from loot_api import initialise_locale
|
||||
|
||||
set_logging_verbosity(LogVerbosity.off)
|
||||
initialise_locale("")
|
||||
|
||||
class GameFixture(unittest.TestCase):
|
||||
game_path = os.path.join(u'.', u'Oblivion')
|
||||
@@ -33,14 +38,14 @@ class GameFixture(unittest.TestCase):
|
||||
class TestLootApi(GameFixture):
|
||||
def test_is_compatible(self):
|
||||
self.assertFalse(is_compatible(0, 9, 0))
|
||||
self.assertTrue(is_compatible(0, 10, 0))
|
||||
self.assertTrue(is_compatible(0, 11, 0))
|
||||
|
||||
def test_version(self):
|
||||
self.assertEqual(Version.major, 0)
|
||||
self.assertEqual(Version.minor, 10)
|
||||
self.assertEqual(Version.patch, 2)
|
||||
self.assertEqual(Version.minor, 11)
|
||||
self.assertEqual(Version.patch, 0)
|
||||
self.assertNotEqual(Version.revision, u'')
|
||||
self.assertEqual(Version.string(), "0.10.2")
|
||||
self.assertEqual(Version.string(), "0.11.0")
|
||||
|
||||
def test_wrapper_version(self):
|
||||
self.assertEqual(WrapperVersion.major, 1)
|
||||
@@ -96,18 +101,10 @@ class TestDatabaseInterface(GameFixture):
|
||||
]))
|
||||
self.assertEqual(tags.removed, set([u'C.Water']))
|
||||
|
||||
# cProfile.runctx('self.test_get_plugin_tags_performance()', globals(), locals(), sort='cumtime')
|
||||
|
||||
# def test_get_plugin_tags_performance(self):
|
||||
# self.db.load_lists(self.masterlist_path, u'')
|
||||
#
|
||||
# for i in xrange(200000):
|
||||
# tags = self.db.get_plugin_tags(u'Unofficial Oblivion Patch.esp')
|
||||
|
||||
def test_get_plugin_messages(self):
|
||||
self.db.load_lists(self.masterlist_path, u'')
|
||||
|
||||
messages = self.db.get_plugin_messages(u'Oblivion.esm', LanguageCode.english)
|
||||
messages = self.db.get_plugin_metadata(u'Oblivion.esm').get_simple_messages(u'en')
|
||||
|
||||
self.assertEqual(len(messages), 1)
|
||||
self.assertEqual(messages[0].type, MessageType.error)
|
||||
|
||||
Reference in New Issue
Block a user