24 Commits
Author SHA1 Message Date
Oliver Hamlet f97de90e02 Update wrapper version to 3.1.1 2018-05-12 21:50:30 +01:00
Oliver Hamlet d00c59b7b2 Update LOOT API to v0.13.2 2018-05-12 21:15:17 +01:00
Oliver Hamlet e06227f437 Build with debug info and package PDB 2018-05-12 19:26:21 +01:00
Oliver Hamlet bcc536d4b0 Downgrade to pybind11 v2.1.1
Updating to v2.2.1 introduced a runtime issue that's
environment-specific but it's not clear what the issue is, so
just downgrade for now.
2018-05-12 19:12:47 +01:00
Oliver Hamlet a564f230be Update wrapper version to 3.1.0
Although the LOOT API update includes breaking changes, none of them are
exposed by the Python wrapper, so this is just a minor update.
2018-04-15 13:16:49 +01:00
Oliver Hamlet 27c8f58494 Update pybind11 to v2.2.2 2018-04-15 13:16:49 +01:00
Oliver Hamlet 179125f006 Expose GameType::tes5vr and GameType::fo4vr 2018-04-15 13:16:49 +01:00
Oliver Hamlet 671ca81beb Update to LOOT API v0.13.1 2018-04-15 13:16:49 +01:00
Oliver Hamlet 7faa360790 Update outdated usage example 2017-12-30 15:29:21 +00:00
Oliver Hamlet 0c9d014174 Remove default value for create_game_handle's game_path argument
The LOOT API incorrectly allows it, it causes a runtime exception.
2017-12-30 15:29:03 +00:00
Oliver Hamlet a8e2b11280 Allow initialise_locale() to be called with no args
Use a blank string as the default argument, as it's the most commonly desired value.
2017-12-30 15:27:48 +00:00
Oliver Hamlet 1275a11be7 Expose load_current_load_order_state() via GameInterface 2017-11-04 17:27:15 +00:00
Oliver Hamlet 5357858069 Update documentation 2017-11-04 13:52:19 +00:00
Oliver Hamlet 04088ac8f4 Update wrapper version to 3.0.0 2017-11-04 12:29:27 +00:00
Oliver Hamlet 7098671ad5 Update to LOOT API v0.12.0
Significant changes include:

- The logging interface has changed, a callback can now be set
  instead of an output file and verbosity, giving clients more
  control.
- DatabaseInterface::EvalLists() has been removed.
- SimpleMessage now has a condition field.
2017-11-04 12:14:26 +00:00
Oliver Hamlet 212f899396 Update to pybind11 v2.2.1 2017-10-17 19:57:42 +01:00
Oliver Hamlet 1e0dbe8dc2 Update to LOOT API v0.11.1 and fix Linux builds 2017-10-17 20:34:45 +01:00
Oliver Hamlet abbc0892fd Update wrapper version to 2.0.0 2017-05-13 08:46:04 +01:00
Oliver Hamlet a94fb19bde 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.
2017-05-13 08:41:42 +01:00
Oliver Hamlet 2823db915a Update to pybind11 v2.1.1 2017-05-13 08:19:30 +01:00
Oliver Hamlet 70371b7647 Deploy tagged builds to GitHub 2016-12-15 20:45:38 +00:00
Oliver Hamlet f5cfa7cc0f Delete old Bintray versions on successful CI run 2016-12-15 20:44:55 +00:00
Oliver Hamlet cf391b0da0 Update to LOOT API v0.10.2 and remove Linux builds
Support for Linux builds is removed as LOOT's snapshot builds are no
longer reliably available, and Linux builds aren't published as part of
LOOT releases. Linux builds could easily be reinstated if LOOT API
binaries become reliably available again.
2016-12-15 20:38:44 +00:00
Oliver Hamlet 58dd19af7d Update Bintray API token used
The previous token was leaked and has been invalidated.
2016-12-05 23:06:46 +00:00
15 changed files with 449 additions and 184 deletions
-47
View File
@@ -1,47 +0,0 @@
sudo: false
language: cpp
compiler: gcc
addons:
apt:
sources:
- ubuntu-toolchain-r-test # ppa:ubuntu-toolchain-r/test
packages:
- gcc-5
- g++-5
- wget
install:
# Use GCC 5.
- if [ "$CXX" = "g++" ]; then export CXX="g++-5" CC="gcc-5"; fi
# Download CMake binary because those available in PPAs either don't support
# xz downloads or don't support HTTPS.
- wget https://cmake.org/files/v3.6/cmake-3.6.2-Linux-x86_64.tar.gz
- tar -xf cmake-3.6.2-Linux-x86_64.tar.gz
before_script:
# Move into the cloned LOOT repo build path.
- mkdir build && cd build
# Link dynamically to the C++ standard library runtime.
- ../cmake-3.6.2-Linux-x86_64/bin/cmake ..
script:
- make all
- python -m unittest test
after_success:
- ../cmake-3.6.2-Linux-x86_64/bin/cpack -C Release
- cd $TRAVIS_BUILD_DIR
# Need to replace the Bintray config files' version placeholders.
- VERSION=$(ls build/package/loot_api_python-*.tar.xz | sed 's/build\/package\/loot_api_python-//;s/-Linux.tar.xz//;')
- sed -i "s/REPLACE_THIS_VERSION/${VERSION}/" scripts/travis/loot-api.bintray.json
deploy:
- provider: bintray
file: scripts/travis/loot-api.bintray.json
user: wrinklyninja
key:
secure: "XUj1hk5lNhyzPNs3iv1kw8h370QrS+hOcGvj7fMkMb3KQF+I7XJIIhi5lcVd/X5NB79M4IYKac+7n4fVPsf6jXd+SpKYKdPF5ZnSn00dtU34Jhz+DiZQoLdAVLhGgOTLxv2SE6kfvfCXXVlSSoVOVNH0rx0OWE/BjZaSxd9+XeQgEJ/qozvt9kl4sd02y/M4r9h4SAMGf3zav+PWy+5cigy/LFONDQ9oeCEOJmVbazlB2Hkt0GnRkPpW/jFjUvt5qs0jS1neBBmeVCxvue1qJVJBwPtIszNhoARn/mY1tfQ4b0MdzvYhK1kjHvtBLW+OoXOr5VaiZ2a0J+t7jtgfO2cadiIgqCbxddltq1CESFa3pSCpkAfSg1jkl3Lj7BJzSLrRLxySN+Hq0O4qR3A3cQOVt5glZIbabq0h1b9jxZSpU9D+jwgZxxmI8NZJRS4TegZ+Q1ygY/MrSydUWQ3fK0ls20GePKjPtK90ipqt0HLyjAcLLVshc1jB3MPqDKEPXnQtxrJmbHwZu2rzlngIjUNybJXQxuJLqcE/awijpoftbqxctXzEq2hMj/lp6Y4agX++hikPg+BP6HHCwuwgXTYkcUXC6v5Mm2NTboDnimiJq2aCzcgc4RVjes1o5cKng8xtpYCNoTkEd4Tu1DL+AR6tJnjXkvRsJCdBWUVIFG4="
skip_cleanup: true
on:
all_branches: true
+19 -8
View File
@@ -30,9 +30,10 @@ configure_file("${CMAKE_SOURCE_DIR}/src/wrapper_version.cpp.in" "${CMAKE_BINARY_
# pybind11
#######################################
set(PYBIND11_URL "https://github.com/pybind/pybind11/archive/v1.8.1.tar.gz")
set(PYBIND11_DOWNLOAD_PATH "${EXTERNAL_PROJECTS_PATH}/pybind11-1.8.1.tar.gz")
set(PYBIND11_EXTRACTED_PATH "${EXTERNAL_PROJECTS_PATH}/pybind11-1.8.1")
set(PYBIND11_VERSION "2.1.1")
set(PYBIND11_URL "https://github.com/pybind/pybind11/archive/v${PYBIND11_VERSION}.tar.gz")
set(PYBIND11_DOWNLOAD_PATH "${EXTERNAL_PROJECTS_PATH}/pybind11-${PYBIND11_VERSION}.tar.gz")
set(PYBIND11_EXTRACTED_PATH "${EXTERNAL_PROJECTS_PATH}/pybind11-${PYBIND11_VERSION}")
if (NOT EXISTS ${PYBIND11_DOWNLOAD_PATH})
file(DOWNLOAD ${PYBIND11_URL} ${PYBIND11_DOWNLOAD_PATH})
@@ -49,9 +50,9 @@ add_subdirectory(${PYBIND11_EXTRACTED_PATH})
#######################################
if (CMAKE_SYSTEM_NAME MATCHES "Windows")
set(LOOT_API_URL "https://bintray.com/wrinklyninja/loot/download_file?file_path=loot-api_0.10.1-0-gd8f8dc4_master.7z")
set(LOOT_API_URL "https://github.com/loot/loot-api/releases/download/0.13.2/loot_api-0.13.2-0-g5956e60_dev-win32.7z")
else()
set(LOOT_API_URL "https://bintray.com/wrinklyninja/loot/download_file?file_path=loot-api_0.10.1-0-gd8f8dc4_master.tar.xz")
set(LOOT_API_URL "https://github.com/loot/loot-api/releases/download/0.13.2/loot-api.tar.xz")
endif()
ExternalProject_Add(loot-api-c++
@@ -84,7 +85,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)
@@ -125,12 +128,20 @@ add_custom_command(TARGET loot_api POST_BUILD
install(TARGETS loot_api
DESTINATION "."
CONFIGURATIONS Release)
CONFIGURATIONS Release RelWithDebInfo)
install(FILES "${LOOT_API_EXTRACTED_PATH}/${LOOT_API_SHARED_LIBRARY}"
"${CMAKE_SOURCE_DIR}/docs/README.md"
DESTINATION "."
CONFIGURATIONS Release)
CONFIGURATIONS Release RelWithDebInfo)
IF (MSVC)
install(FILES $<TARGET_PDB_FILE:loot_api>
DESTINATION .
OPTIONAL
CONFIGURATIONS RelWithDebInfo
RENAME loot_api_python.pdb)
ENDIF ()
########################################
# CPack
+1 -1
View File
@@ -5,7 +5,7 @@ LOOT API Python Module
[![Travis Build Status](https://travis-ci.org/loot/loot-api-python.svg?branch=master)](https://travis-ci.org/loot/loot-api-python)
[![Documentation Status](https://readthedocs.org/projects/loot-api-python/badge/)](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
+26 -4
View File
@@ -2,7 +2,14 @@ os: Visual Studio 2015
version: "{build}-{branch}"
configuration: Release
configuration: RelWithDebInfo
environment:
bintray_auth_token:
secure: fBQJmUDK/EgEUWjjbo6bWcitczeFTJZT4OZ3ZZ4FoUT6soBsTWPQJnr8YEVMFhGP
install:
- ps: (New-Object Net.WebClient).DownloadFile('https://raw.githubusercontent.com/WrinklyNinja/ci-scripts/1.1.0/delete_old_bintray_versions.py', "$env:APPVEYOR_BUILD_FOLDER\delete_old_bintray_versions.py")
before_build:
- cd %APPVEYOR_BUILD_FOLDER%
@@ -15,12 +22,12 @@ build:
project: 'c:\projects\loot-api-python\build\loot_api_python.sln'
test_script:
- cd %APPVEYOR_BUILD_FOLDER%\build\Release
- cd %APPVEYOR_BUILD_FOLDER%\build\%CONFIGURATION%
- python -m unittest test
after_test:
- cd %APPVEYOR_BUILD_FOLDER%\build
- cpack
- cpack -C %CONFIGURATION%
# AppVeyor checks out a specific commit, but that means the archive script
# can't tell which branch it's on, so rename the 7z archives.
- ps: $env:GIT_DESCRIBE = ((git describe --tags --long --always) | Out-String) -replace "`n|`r", ""
@@ -33,10 +40,25 @@ deploy:
- provider: BinTray
username: wrinklyninja
api_key:
secure: u234T2688DZmz4JH5+0iAHcUcL2fEIGculb8655bn4B1q7GckhplsitzgEbv3NFc
secure: fBQJmUDK/EgEUWjjbo6bWcitczeFTJZT4OZ3ZZ4FoUT6soBsTWPQJnr8YEVMFhGP
subject: wrinklyninja
repo: loot
package: loot-api-python
version: $(GIT_DESCRIBE)_$(APPVEYOR_REPO_BRANCH)
publish: true
artifact: loot_api_python
- provider: GitHub
tag: $(APPVEYOR_REPO_TAG_NAME)
release: LOOT API Python Module v$(APPVEYOR_REPO_TAG_NAME)
description: |
Requires Windows 7 or later and the [MSVC 2015 x86 redistributable](https://download.microsoft.com/download/6/A/A/6AA4EDFF-645B-48C5-81CC-ED5963AEAD48/vc_redist.x86.exe), and [7-Zip](http://www.7-zip.org/) to extract the archive.
auth_token:
secure: V1GojGQfrAiQtUWtNNXfm3samiH+1yNF5UYhkn8B8mbif20IGTGWNlBS9E4S0SUC
artifact: loot_api_python
draft: false
on:
appveyor_repo_tag: true
on_success:
- ps: python "$env:APPVEYOR_BUILD_FOLDER\delete_old_bintray_versions.py" -o loot -g loot-api-python -u wrinklyninja -b loot -p loot-api-python -t $env:bintray_auth_token -n 30
+1 -1
View File
@@ -346,5 +346,5 @@ texinfo_documents = [
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {
'loot_api': ('http://loot.readthedocs.io/en/0.10.1/', None),
'loot_api': ('http://loot.readthedocs.io/en/0.10.2/', None),
}
+72 -37
View File
@@ -14,8 +14,7 @@ values are unsigned integer constants.
.. py:class:: loot_api.GameType
Wraps :cpp:type:`loot::GameType` to expose the LOOT API's game
codes.
Wraps :cpp:type:`loot::GameType` to expose the LOOT API's game codes.
.. py:attribute:: fo3
.. py:attribute:: fo4
@@ -24,27 +23,21 @@ values are unsigned integer constants.
.. py:attribute:: tes5
.. py:attribute:: tes5se
.. py:class:: loot_api.LanguageCode
.. py:class:: loot_api.LogLevel
Wraps :cpp:type:`loot::LanguageCode` to expose the LOOT API's
language codes.
Wraps :cpp:type:`loot::LogLevel` to expose the LOOT API's log level codes.
.. py:attribute:: english
.. py:attribute:: spanish
.. py:attribute:: russian
.. py:attribute:: french
.. py:attribute:: chinese
.. py:attribute:: polish
.. py:attribute:: brazilian_portuguese
.. py:attribute:: finnish
.. py:attribute:: german
.. py:attribute:: danish
.. py:attribute:: korean
.. py:attribute:: trace
.. py:attribute:: debug
.. py:attribute:: info
.. py:attribute:: warning
.. py:attribute:: error
.. py:attribute:: fatal
.. py:class:: loot_api.MessageType
Wraps :cpp:type:`loot::MessageType` to expose the LOOT API's
message type codes.
Wraps :cpp:type:`loot::MessageType` to expose the LOOT API's message type
codes.
.. py:attribute:: error
.. py:attribute:: say
@@ -52,13 +45,26 @@ values are unsigned integer constants.
.. py:class:: loot_api.PluginCleanliness
Wraps :cpp:type:`loot::PluginCleanliness` to expose the LOOT API's plugin cleanliness state codes.
Codes used to indicate the cleanliness of a plugin according to the
information contained within the loaded masterlist/userlist.
.. py:attribute:: clean
Indicates that the plugin is clean.
.. py:attribute:: dirty
Indicates that the plugin is dirty.
.. py:attribute:: do_not_clean
Indicates that the plugin contains dirty edits, but that they are part of
the plugin’s intended functionality and should not be removed.
.. py:attribute:: unknown
Indicates that no data is available on whether the plugin is dirty or not.
Public-Field Data Structures
============================
@@ -81,7 +87,7 @@ Classes with public fields and no member functions.
A boolean that is true if the masterlist has been modified from its state
at the commit given by :py:attr:`revision_id`.
.. py:class:: loot_api.Message
.. py:class:: loot_api.SimpleMessage
Wraps :cpp:class:`loot::SimpleMessage`.
@@ -91,12 +97,16 @@ Classes with public fields and no member functions.
.. py:attribute:: language
A :py:class:`loot_api.LanguageCode` giving the message text language.
A Unicode string giving the message text language.
.. py:attribute:: text
A Unicode string containing the message text.
.. py:attribute:: condition
A Unicode string containing the message condition.
.. py:class:: loot_api.PluginTags
Wraps :cpp:class:`loot::PluginTags`.
@@ -117,49 +127,65 @@ Classes with public fields and no member functions.
Functions
=========
.. py:function:: loot_api.set_logging_callback(callback) -> NoneType
Set the callback function that is called when logging. Wraps
:cpp:func:`loot::SetLoggingCallback`.
.. py:function:: loot_api.is_compatible(int, int, int) -> bool
Checks for API compatibility. Wraps :cpp:func:`loot::IsCompatible`.
.. py:function:: loot_api.create_database(game : loot_api.GameType, [game_path : unicode = u'', [game_local_path : unicode = u'']]) -> loot_api.DatabaseInterface
.. py:function:: loot_api.InitialiseLocale(unicode = u'') -> NoneType
Initialise a new database handle. Wraps :cpp:func:`loot::IsCompatible`.
Initialise the current global locale using the given ID. A blank value means
that the system default locale will be initialised. Wraps
:cpp:func:`loot::InitialiseLocale`.
.. py:function:: loot_api.create_game_handle(game : loot_api.GameType, game_path : unicode, [game_local_path : unicode = u'']) -> loot_api.GameInterface
Initialise a new game handle. Wraps :cpp:func:`loot::CreateGameHandle`.
Classes
=======
.. py:class:: loot_api.GameInterface
Wraps :cpp:class:`loot::GameInterface`.
.. py:function:: loot_api.get_database() -> loot_api.DatabaseInterface
Get a database handle. Wraps :cpp:func:`loot::GetDatabase`.
.. py:function:: loot_api.load_current_load_order_state() -> NoneType
Load the current load order state, discarding any previously held state.
Wraps :cpp:func:`loot::LoadCurrentLoadOrderState`.
.. py:class:: loot_api.DatabaseInterface
Wraps :cpp:class:`loot::DatabaseInterface`.
.. py:method:: eval_lists(loot_api.DatabaseInterface) -> NoneType
Evaluates all conditions and regular expression metadata entries in the loaded metadata lists. Wraps :cpp:func:`EvalLists`.
.. py:method:: get_masterlist_revision(loot_api.DatabaseInterface, unicode, bool) -> loot_api.MasterlistInfo
Gets the give masterlist’s source control revision. Wraps :cpp:func:`GetMasterlistRevision`.
.. py:method:: get_plugin_cleanliness(loot_api.DatabaseInterface, unicode) -> loot_api.PluginCleanliness
.. py:method:: get_plugin_metadata(loot_api.DatabaseInterface, plugin : unicode, [includeUserMetadata : bool = True, [evaluateConditions : bool = False]]) -> loot_api.PluginMetadata
Determines the database’s knowledge of a plugin’s cleanliness. Wraps :cpp:func:`GetPluginCleanliness`.
Get all a plugin’s loaded metadata. Wraps :cpp:func:`GetPluginMetadata`.
.. py:method:: get_plugin_messages(loot_api.DatabaseInterface, unicode, loot_api.LanguageCode) -> list<loot_api.Message>
.. py:method:: get_plugin_cleanliness(loot_api.DatabaseInterface, plugin : unicode, [evaluateConditions : bool = False]) -> loot_api.PluginCleanliness
Outputs the messages associated with the given plugin in the database. Wraps :cpp:func:`GetPluginMessages`.
Determines the database’s knowledge of a plugin’s cleanliness. Outputs whether the plugin should be cleaned or not, or if no data is available.
.. py:method:: get_plugin_tags(loot_api.DatabaseInterface, unicode) -> loot_api.PluginTags
.. py:method:: get_plugin_tags(loot_api.DatabaseInterface, plugin : unicode, [evaluateConditions : bool = False]) -> loot_api.PluginTags
Outputs the Bash Tags suggested for addition and removal by the database for the given plugin. Wraps :cpp:func:`GetPluginTags`.
Outputs the Bash Tags suggested for addition and removal by the database for the given plugin.
.. py:method:: load_lists(loot_api.DatabaseInterface, masterlist_path : unicode, [userlist_path : unicode = u'']) -> NoneType
Loads the masterlist and userlist from the paths specified. Wraps :cpp:func:`LoadLists`.
.. py:method:: sort_plugins(loot_api.DatabaseInterface, list<unicode>) -> list<unicode>
Calculates a new load order for all a game’s installed plugins and outputs the sorted order. Wraps :cpp:func:`SortPlugins`.
.. py:method:: update_masterlist(loot_api.DatabaseInterface, unicode, unicode, unicode) -> bool
Updates the given masterlist using the given Git repository details. Wraps :cpp:func:`UpdateMasterlist`.
@@ -216,3 +242,12 @@ Classes
.. py:staticmethod:: string() -> unicode
Returns the API version as a string of the form ``major.minor.patch``
.. py:class:: loot_api.PluginMetadata
Wraps :cpp:class:`loot::PluginMetadata`.
.. py:method:: get_simple_messages(loot_api.PluginMetadata, unicode) -> list<loot_api.SimpleMessage>
Get the plugin’s messages as SimpleMessage objects for the given language.
Wraps :cpp:func:`GetPluginMessages`.
+4 -3
View File
@@ -28,7 +28,7 @@ To check if the module loaded is compatible with the version of the API that you
developed against::
>>> import loot_api
>>> loot_api.is_compatible(0,10,0)
>>> loot_api.is_compatible(0,12,0)
True
>>> loot_api.is_compatible(0,9,0)
False
@@ -39,8 +39,9 @@ Getting a Plugin's Bash Tag Suggestions
To get a plugin's Bash Tag suggestions from a ``masterlist.yaml`` metadata file::
>>> import loot_api
>>> db = loot_api.create_database(loot_api.GameType.tes4, '', '')
>>> db.load_lists('masterlist.yaml', '')
>>> loot_api.initialise_locale()
>>> db = loot_api.create_game_handle(loot_api.GameType.tes4, 'C:\\path\\to\\oblivion\\directory')
>>> db.load_lists('masterlist.yaml')
>>> tags = db.get_plugin_tags(u'Unofficial Oblivion Patch.esp')
>>> tags.added
set([u'Scripts', u'Relations', u'C.Owner', u'Actors.AIPackages', u'Actors.Stats', u'Actors.ACBS', u'C.Music', u'Factions', u'Invent', u'Relev', u'Names', u'C.Light', u'Delev', u'C.Name', u'C.Climate', u'NPC.Class', u'Stats', u'Actors.DeathItem', u'Creatures.Blood', u'Actors.CombatStyle', u'Actors.AIData'])
-15
View File
@@ -1,15 +0,0 @@
{
"package": {
"name": "loot-api-python",
"repo": "loot",
"subject": "wrinklyninja"
},
"version": {
"name": "REPLACE_THIS_VERSION"
},
"files": [{
"includePattern": "build/package/(loot_api_python-.+\\.tar.xz)",
"uploadPattern": "$1"
}],
"publish": true
}
+74
View File
@@ -0,0 +1,74 @@
/* 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 {
PluginTags GetPluginTags(const std::shared_ptr<DatabaseInterface> db, const std::string& plugin, bool evaluateConditions) {
PluginTags tags;
auto metadata = db->GetPluginMetadata(plugin, false, evaluateConditions);
for (const auto &tag : metadata.GetTags()) {
if (tag.IsAddition())
tags.added.insert(tag.GetName());
else
tags.removed.insert(tag.GetName());
}
metadata = db->GetPluginUserMetadata(plugin, evaluateConditions);
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, bool evaluateConditions) {
auto metadata = db->GetPluginMetadata(plugin, true, evaluateConditions);
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;
}
}
+46
View File
@@ -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 {
PluginTags GetPluginTags(const std::shared_ptr<DatabaseInterface> db,
const std::string& plugin,
bool evaluateConditions = false);
PluginCleanliness GetPluginCleanliness(const std::shared_ptr<DatabaseInterface> db,
const std::string& plugin,
bool evaluateConditions = false);
}
#endif
+70 -45
View File
@@ -25,53 +25,35 @@
#include <loot/api.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include "convenience.h"
#include "wrapper_version.h"
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>);
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_;
const std::string emptyString;
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)
.value("tes5se", GameType::tes5se)
.value("tes5vr", GameType::tes5vr)
.value("fo3", GameType::fo3)
.value("fonv", GameType::fonv)
.value("fo4", GameType::fo4);
.value("fo4", GameType::fo4)
.value("fo4vr", GameType::fo4vr);
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_<LogLevel>(module, "LogLevel")
.value("trace", LogLevel::trace)
.value("debug", LogLevel::debug)
.value("info", LogLevel::info)
.value("warning", LogLevel::warning)
.value("error", LogLevel::error)
.value("fatal", LogLevel::fatal);
enum_<MessageType>(module, "MessageType")
.value("say", MessageType::say)
@@ -83,22 +65,30 @@ 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);
.def_readwrite("text", &SimpleMessage::text)
.def_readwrite("condition", &SimpleMessage::condition);
class_<PluginTags>(module, "PluginTags")
.def_readwrite("added", &PluginTags::added)
.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")
.def_readonly_static("major", &LootVersion::major)
.def_readonly_static("minor", &LootVersion::minor)
@@ -112,21 +102,56 @@ 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_<GameInterface, std::shared_ptr<GameInterface>>(module, "GameInterface")
.def("load_current_load_order_state", &GameInterface::LoadCurrentLoadOrderState)
.def("get_database", &GameInterface::GetDatabase);
class_<DatabaseInterface, std::shared_ptr<DatabaseInterface>>(module, "DatabaseInterface")
.def("load_lists", &DatabaseInterface::LoadLists, arg("masterlist_path"), arg("userlist_path") = emptyString)
.def("eval_lists", &DatabaseInterface::EvalLists)
.def("sort_plugins", &DatabaseInterface::SortPlugins)
.def("load_lists", &DatabaseInterface::LoadLists, arg("masterlist_path"), arg("userlist_path") = "")
.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,
arg("plugin"),
arg("evaluateConditions") = false)
.def("get_plugin_cleanliness", &GetPluginCleanliness,
arg("plugin"),
arg("evaluateConditions") = false)
.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_callback", &SetLoggingCallback);
module.def("is_compatible", &IsCompatible);
module.def("create_database", &CreateDatabase, arg("game"), arg("game_path") = emptyString, arg("game_local_path") = emptyString);
module.def("initialise_locale", &InitialiseLocale, arg("id") = "");
module.def("create_game_handle", &CreateGameHandle,
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();
}
+52
View File
@@ -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
+58
View File
@@ -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
+24 -21
View File
@@ -7,11 +7,18 @@ 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 SimpleMessage
from loot_api import MessageType
from loot_api import create_database
from loot_api import create_game_handle
from loot_api import is_compatible
from loot_api import set_logging_callback
from loot_api import initialise_locale
def logging_callback(level, message):
pass
set_logging_callback(logging_callback)
initialise_locale()
class GameFixture(unittest.TestCase):
game_path = os.path.join(u'.', u'Oblivion')
@@ -33,25 +40,26 @@ 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, 13, 0))
def test_version(self):
self.assertEqual(Version.major, 0)
self.assertEqual(Version.minor, 10)
self.assertEqual(Version.patch, 1)
self.assertEqual(Version.minor, 13)
self.assertEqual(Version.patch, 2)
self.assertNotEqual(Version.revision, u'')
self.assertEqual(Version.string(), "0.10.1")
self.assertEqual(Version.string(), "0.13.2")
def test_wrapper_version(self):
self.assertEqual(WrapperVersion.major, 1)
self.assertEqual(WrapperVersion.major, 3)
self.assertEqual(WrapperVersion.minor, 1)
self.assertEqual(WrapperVersion.patch, 2)
self.assertEqual(WrapperVersion.patch, 1)
self.assertNotEqual(WrapperVersion.revision, u'')
self.assertNotEqual(WrapperVersion.revision, Version.revision)
self.assertEqual(WrapperVersion.string(), "1.1.2")
self.assertEqual(WrapperVersion.string(), "3.1.1")
def test_create_db(self):
db = create_database(GameType.tes4, self.game_path, self.local_path)
game = create_game_handle(GameType.tes4, self.game_path, self.local_path)
db = game.get_database()
self.assertNotEqual(db, None)
class TestDatabaseInterface(GameFixture):
@@ -60,7 +68,10 @@ class TestDatabaseInterface(GameFixture):
def setUp(self):
super(TestDatabaseInterface, self).setUp()
self.db = create_database(GameType.tes4, self.game_path, self.local_path)
game = create_game_handle(GameType.tes4, self.game_path, self.local_path)
game.load_current_load_order_state()
self.db = game.get_database()
def test_load_lists(self):
self.db.load_lists(self.masterlist_path, u'')
@@ -96,18 +107,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)
+2 -2
View File
@@ -25,9 +25,9 @@
#include "wrapper_version.h"
namespace loot {
const unsigned int WrapperVersion::major = 1;
const unsigned int WrapperVersion::major = 3;
const unsigned int WrapperVersion::minor = 1;
const unsigned int WrapperVersion::patch = 2;
const unsigned int WrapperVersion::patch = 1;
const std::string WrapperVersion::revision = "@GIT_COMMIT_STRING@";
std::string WrapperVersion::string() {