From bf2557ada81564bae0f03e3213e50e9e3a5100dc Mon Sep 17 00:00:00 2001 From: Kristofer Berggren Date: Wed, 6 May 2020 18:55:46 +0800 Subject: [PATCH] fixes #5 - add support for macOS and python 3 --- .travis.yml | 22 ++++++++++++++++++---- CMakeLists.txt | 8 ++++---- README.md | 41 ++++++++++++++++++++++++++++------------- run.sh | 6 ++++++ src/spacy/doc.cpp | 11 ++++------- src/spacy/python.cpp | 14 +++++++++++++- src/spacy/python.h | 29 ++++++++++++++++++++++++++++- src/spacy/span.cpp | 6 +++--- src/spacy/span.h | 8 ++++---- 9 files changed, 108 insertions(+), 37 deletions(-) create mode 100755 run.sh diff --git a/.travis.yml b/.travis.yml index efa3fac..5167901 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,19 +6,33 @@ sudo: os: - linux + - osx dist: - bionic +osx_image: + - xcode11 + addons: apt: packages: - - libpython2.7-dev + - cmake + - python3-pip + - libpython3-dev + brew: + packages: + - cmake + - python install: - - sudo pip install -U spacy - - sudo pip install -U --upgrade cryptography - - sudo python -m spacy download en_core_web_sm + - which python + - python --version + - which python3 + - python3 --version + - pip3 install -U spacy + - pip3 install -U --upgrade cryptography + - sudo python3 -m spacy download en_core_web_sm script: - mkdir -p build diff --git a/CMakeLists.txt b/CMakeLists.txt index c66d7e6..beb8d4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,14 +2,14 @@ # # URL: https://github.com/d99kris/spacy-cpp # -# Copyright (C) 2017 Kristofer Berggren +# Copyright (C) 2017-2020 Kristofer Berggren # All rights reserved. # # spacy-cpp is distributed under the MIT license, see LICENSE for details. # Project cmake_minimum_required(VERSION 3.1 FATAL_ERROR) -project(spacy-cpp VERSION 1.02 LANGUAGES CXX) +project(spacy-cpp VERSION 1.03 LANGUAGES CXX) set (CMAKE_CXX_STANDARD 11) if(MSVC) if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]") @@ -22,8 +22,8 @@ else() -Wcast-qual -Wno-missing-braces -Wswitch-default -Wunreachable-code \ -Wundef -Wuninitialized -Wcast-align") endif() -find_package(PythonLibs 2.7 REQUIRED) -find_package(PythonInterp 2.7 REQUIRED) +find_package(PythonLibs 3 REQUIRED) +find_package(PythonInterp 3 REQUIRED) # Library add_library(spacy SHARED diff --git a/README.md b/README.md index 97d961f..80e418f 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ Spacy-cpp ========= -| **Linux** | -|-----------| +| **Linux + Mac** | +|-----------------| | [![Build status](https://travis-ci.com/d99kris/spacy-cpp.svg?branch=master)](https://travis-ci.com/d99kris/spacy-cpp) | Spacy-cpp is a C++ wrapper library for the excellent NLP library [spaCy](https://spacy.io/). @@ -12,8 +12,8 @@ The goal of spacy-cpp is to expose the functionality of spaCy to C++ application an API that is similar to that of spaCy, enabling rapid development in Python and simple porting to C++. -Spacy-cpp is under development and does not yet support all API's of spaCy, refer -to the API Documentation section below. +Spacy-cpp is under development and does not yet support all API's of spaCy, refer to the +API Documentation section below. Example Usage @@ -39,25 +39,39 @@ for token in doc: Supported Platforms =================== -Spacy-cpp is implemented using C++11 with the intention of being portable. It's however only been tested on: -- Linux / Ubuntu 16.04 LTS +Spacy-cpp is implemented using C++11 with the intention of being portable. Current version has been +tested on: +- macOS 10.15 Catalina +- Ubuntu 20.04 LTS Pre-requisites ============== -Spacy-cpp requires libpython, spaCy and typically a spaCy model. +Spacy-cpp requires python development library, pip, spaCy and typically a spaCy model. + +macOS +----- +Install build dependencies: + + brew install cmake python + +Install spaCy and an English model: + + pip3 install -U spacy + python3 -m spacy download en_core_web_sm Ubuntu ------ +Install build dependencies: -Install libpython 2.7: - - sudo apt install libpython2.7-dev + sudo apt install cmake python3-pip libpython3-dev -Install spaCy and an English model: +Install spaCy and an English model (if the python3 command fails with segmentation fault, +it could be this bug https://github.com/explosion/spaCy/issues/4838 and a possible workaround +is to call the prepend command with `sudo`): - pip install -U spacy - python -m spacy download en_core_web_sm + pip3 install -U spacy + python3 -m spacy download en_core_web_sm Installation @@ -215,6 +229,7 @@ Spacy-cpp uses cmake for its tests. Commands to build and execute the test suite mkdir -p build && cd build && cmake .. && make && ctest --output-on-failure ; cd - + License ======= Spacy-cpp is distributed under the MIT license. diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..e826fe4 --- /dev/null +++ b/run.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +# run tests +mkdir -p build && cd build && cmake .. && make && ctest --output-on-failure + +exit ${?} diff --git a/src/spacy/doc.cpp b/src/spacy/doc.cpp index 3d54a3e..c51637d 100644 --- a/src/spacy/doc.cpp +++ b/src/spacy/doc.cpp @@ -2,7 +2,7 @@ // // URL: https://github.com/d99kris/spacy-cpp // -// Copyright (C) 2017 Kristofer Berggren +// Copyright (C) 2017-2020 Kristofer Berggren // All rights reserved. // // spacy-cpp is distributed under the MIT license, see LICENSE for details. @@ -34,8 +34,7 @@ namespace Spacy std::vector Doc::ents() const { - std::vector spans(Python::get_attr_vector(m_doc, "ents")); - std::for_each(spans.begin(), spans.end(), std::bind2nd(std::mem_fun_ref(&Span::set_parent), this)); + std::vector spans(Python::get_attr_vector_ctor_arg(m_doc, "ents", this)); return spans; } @@ -56,8 +55,7 @@ namespace Spacy std::vector Doc::noun_chunks() const { - std::vector spans(Python::get_attr_vector(m_doc, "noun_chunks")); - std::for_each(spans.begin(), spans.end(), std::bind2nd(std::mem_fun_ref(&Span::set_parent), this)); + std::vector spans(Python::get_attr_vector_ctor_arg(m_doc, "noun_chunks", this)); return spans; } @@ -68,8 +66,7 @@ namespace Spacy std::vector Doc::sents() const { - std::vector spans(Python::get_attr_vector(m_doc, "sents")); - std::for_each(spans.begin(), spans.end(), std::bind2nd(std::mem_fun_ref(&Span::set_parent), this)); + std::vector spans(Python::get_attr_vector_ctor_arg(m_doc, "sents", this)); return spans; } diff --git a/src/spacy/python.cpp b/src/spacy/python.cpp index cc8f879..ba75637 100644 --- a/src/spacy/python.cpp +++ b/src/spacy/python.cpp @@ -2,7 +2,7 @@ // // URL: https://github.com/d99kris/spacy-cpp // -// Copyright (C) 2017 Kristofer Berggren +// Copyright (C) 2017-2020 Kristofer Berggren // All rights reserved. // // spacy-cpp is distributed under the MIT license, see LICENSE for details. @@ -32,7 +32,11 @@ namespace Spacy } Python::Python() +#if (PY_MAJOR_VERSION >= 3) + : m_argv(std::make_shared(nullptr)) +#else : m_argv(std::make_shared(nullptr)) +#endif { Py_Initialize(); PySys_SetArgv(0, m_argv.get()); @@ -55,7 +59,11 @@ namespace Spacy template <> long Python::Convert::get_value(PyObjectPtr p_obj) { +#if (PY_MAJOR_VERSION >= 3) + assert(PyLong_Check(p_obj.get())); +#else assert(PyLong_Check(p_obj.get()) || PyInt_Check(p_obj.get())); +#endif return PyLong_AsLong(p_obj.get()); } @@ -98,7 +106,11 @@ namespace Spacy template <> PyObjectPtr Python::Convert::get_object(long p_val) { +#if (PY_MAJOR_VERSION >= 3) + return PyObjectPtr(PyLong_FromLong(p_val)); +#else return PyObjectPtr(PyInt_FromLong(p_val)); +#endif } template <> diff --git a/src/spacy/python.h b/src/spacy/python.h index 1861560..2fb73ec 100644 --- a/src/spacy/python.h +++ b/src/spacy/python.h @@ -2,7 +2,7 @@ // // URL: https://github.com/d99kris/spacy-cpp // -// Copyright (C) 2017 Kristofer Berggren +// Copyright (C) 2017-2020 Kristofer Berggren // All rights reserved. // // spacy-cpp is distributed under the MIT license, see LICENSE for details. @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -73,6 +74,14 @@ namespace Spacy return get_vector(attr); } + template + static std::vector get_attr_vector_ctor_arg(PyObjectPtr p_obj, const std::string& p_attr, U p_arg) + { + assert(PyObject_HasAttrString(p_obj.get(), p_attr.c_str())); + PyObjectPtr attr(PyObject_GetAttrString(p_obj.get(), p_attr.c_str())); + return get_vector_ctor_arg(attr, p_arg); + } + template static std::map get_map(PyObjectPtr p_obj) { @@ -116,6 +125,20 @@ namespace Spacy return items; } + template + static std::vector get_vector_ctor_arg(PyObjectPtr p_obj, U p_arg) + { + assert(PySequence_Check(p_obj.get()) || PyIter_Check(p_obj.get())); + PyObjectPtr list(PySequence_List(p_obj.get())); + Py_ssize_t size = PySequence_Size(list.get()); + std::vector items; + for (Py_ssize_t i = 0; i < size; ++i) + { + items.push_back(T(PyObjectPtr(PySequence_GetItem(list.get(), i)), p_arg)); + } + return items; + } + static PyObjectPtr import(const std::string& p_name) { PyObjectPtr name(Python::get_object(p_name)); @@ -146,7 +169,11 @@ namespace Spacy static bool Custom_PyFloat_Check(PyObjectPtr p_obj); private: +#if (PY_MAJOR_VERSION >= 3) + std::shared_ptr m_argv; +#else std::shared_ptr m_argv; +#endif }; template <> diff --git a/src/spacy/span.cpp b/src/spacy/span.cpp index 1c4c9ed..242c052 100644 --- a/src/spacy/span.cpp +++ b/src/spacy/span.cpp @@ -2,7 +2,7 @@ // // URL: https://github.com/d99kris/spacy-cpp // -// Copyright (C) 2017 Kristofer Berggren +// Copyright (C) 2017-2020 Kristofer Berggren // All rights reserved. // // spacy-cpp is distributed under the MIT license, see LICENSE for details. @@ -22,7 +22,7 @@ namespace Spacy { } - Doc* Span::doc() const + const Doc* Span::doc() const { return m_parent; } @@ -77,7 +77,7 @@ namespace Spacy return Python::get_attr_value(m_span, "vector_norm"); } - Span::Span(PyObjectPtr p_span, Doc* p_parent /* = nullptr */) + Span::Span(PyObjectPtr p_span, const Doc* p_parent /* = nullptr */) : m_span(p_span) , m_parent(p_parent) { diff --git a/src/spacy/span.h b/src/spacy/span.h index 2302a08..9760f97 100644 --- a/src/spacy/span.h +++ b/src/spacy/span.h @@ -2,7 +2,7 @@ // // URL: https://github.com/d99kris/spacy-cpp // -// Copyright (C) 2017 Kristofer Berggren +// Copyright (C) 2017-2020 Kristofer Berggren // All rights reserved. // // spacy-cpp is distributed under the MIT license, see LICENSE for details. @@ -28,7 +28,7 @@ namespace Spacy public: virtual ~Span(); - Doc* doc() const; + const Doc* doc() const; long label() const; std::string label_() const; std::string lemma_() const; @@ -41,13 +41,13 @@ namespace Spacy double vector_norm() const; private: - Span(PyObjectPtr p_span, Doc* p_parent = nullptr); + Span(PyObjectPtr p_span, const Doc* p_parent = nullptr); void set_parent(Doc* p_parent); private: PyObjectPtr m_span; - Doc* m_parent; + const Doc* m_parent; }; }