././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1585174471.6204531 cppy-1.1.0/0000755000076500000240000000000000000000000013726 5ustar00mdartiailhstaff00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1532995026.0 cppy-1.1.0/LICENSE0000644000076500000240000000271500000000000014740 0ustar00mdartiailhstaff00000000000000Copyright (c) 2014, Nucleic All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1585174469.0 cppy-1.1.0/MANIFEST.in0000644000076500000240000000055600000000000015472 0ustar00mdartiailhstaff00000000000000include MANIFEST.in include *.rst include LICENSE recursive-include cppy *.py recursive-include cppy *.h recursive-include docs/source *.rst recursive-include docs/source *.png recursive-include docs/source *.py recursive-include tests/ *.py include docs/make.bat include docs/Makefile recursive-include tests *.py prune .git prune dist prune build prune docs/build ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1585174471.6200557 cppy-1.1.0/PKG-INFO0000644000076500000240000000131500000000000015023 0ustar00mdartiailhstaff00000000000000Metadata-Version: 1.0 Name: cppy Version: 1.1.0 Summary: C++ headers for C extension development Home-page: https://github.com/nucleic/cppy Author: The Nucleic Development Team Author-email: sccolbert@gmail.com License: UNKNOWN Description: cppy ==== .. image:: https://travis-ci.org/nucleic/cppy.svg?branch=master :target: https://travis-ci.org/nucleic/cppy A small C++ header library which makes it easier to write Python extension modules. The primary feature is a PyObject smart pointer which automatically handles reference counting and provides convenience methods for performing common object operations. Platform: UNKNOWN ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1579137253.0 cppy-1.1.0/README.rst0000644000076500000240000000057100000000000015420 0ustar00mdartiailhstaff00000000000000cppy ==== .. image:: https://travis-ci.org/nucleic/cppy.svg?branch=master :target: https://travis-ci.org/nucleic/cppy A small C++ header library which makes it easier to write Python extension modules. The primary feature is a PyObject smart pointer which automatically handles reference counting and provides convenience methods for performing common object operations. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1585174471.6114085 cppy-1.1.0/cppy/0000755000076500000240000000000000000000000014701 5ustar00mdartiailhstaff00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1585174322.0 cppy-1.1.0/cppy/__init__.py0000644000076500000240000000115500000000000017014 0ustar00mdartiailhstaff00000000000000#------------------------------------------------------------------------------ # Copyright (c) 2014-2020, Nucleic # # Distributed under the terms of the BSD 3-Clause License. # # The full license is in the file LICENSE, distributed with this software. #------------------------------------------------------------------------------ __major_version__ = 1 __minor_version__ = 1 __patch_version__ = 0 __version_info__ = (__major_version__, __minor_version__, __patch_version__) __version__ = '%s.%s.%s' % __version_info__ def get_include(): import os return os.path.join(os.path.dirname(__file__), 'include') ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1585174471.6091576 cppy-1.1.0/cppy/include/0000755000076500000240000000000000000000000016324 5ustar00mdartiailhstaff00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1585174471.6153505 cppy-1.1.0/cppy/include/cppy/0000755000076500000240000000000000000000000017277 5ustar00mdartiailhstaff00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1585174326.0 cppy-1.1.0/cppy/include/cppy/cppy.h0000644000076500000240000000133000000000000020420 0ustar00mdartiailhstaff00000000000000/*----------------------------------------------------------------------------- | Copyright (c) 2014-2020, Nucleic | | Distributed under the terms of the BSD 3-Clause License. | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ #pragma once #define pyobject_cast( o ) ( reinterpret_cast( o ) ) #define pytype_cast( o ) ( reinterpret_cast( o ) ) // Used to cast PyDoc_STRVAR to void* in PyType_Slot #define cast_py_tp_doc( o ) ( reinterpret_cast( const_cast( o ) ) ) #define void_cast( o ) ( reinterpret_cast( o ) ) #include "defines.h" #include "errors.h" #include "ptr.h" ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1585174325.0 cppy-1.1.0/cppy/include/cppy/defines.h0000644000076500000240000000074500000000000021073 0ustar00mdartiailhstaff00000000000000/*----------------------------------------------------------------------------- | Copyright (c) 2014-2020, Nucleic | | Distributed under the terms of the BSD 3-Clause License. | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ #pragma once #include #define CPPY_MAJOR_VERSION 1 #define CPPY_MINOR_VERSION 1 #define CPPY_PATCH_VERSION 0 #define CPPY_VERSION "1.1.0" ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1585174327.0 cppy-1.1.0/cppy/include/cppy/errors.h0000644000076500000240000000261100000000000020764 0ustar00mdartiailhstaff00000000000000/*----------------------------------------------------------------------------- | Copyright (c) 2014-2020, Nucleic | | Distributed under the terms of the BSD 3-Clause License. | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ #pragma once #include namespace cppy { inline PyObject* system_error( const char* message ) { PyErr_SetString( PyExc_SystemError, message ); return 0; } inline PyObject* type_error( const char* message ) { PyErr_SetString( PyExc_TypeError, message ); return 0; } inline PyObject* type_error( PyObject* ob, const char* expected ) { PyErr_Format( PyExc_TypeError, "Expected object of type `%s`. Got object of type `%s` instead.", expected, ob->ob_type->tp_name ); return 0; } inline PyObject* value_error( const char* message ) { PyErr_SetString( PyExc_ValueError, message ); return 0; } inline PyObject* runtime_error( const char* message ) { PyErr_SetString( PyExc_RuntimeError, message ); return 0; } inline PyObject* attribute_error( const char* message ) { PyErr_SetString( PyExc_AttributeError, message ); return 0; } inline PyObject* attribute_error( PyObject* ob, const char* attr ) { PyErr_Format( PyExc_AttributeError, "'%s' object has no attribute '%s'", ob->ob_type->tp_name, attr ); return 0; } } // namespace cppy ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1585174328.0 cppy-1.1.0/cppy/include/cppy/ptr.h0000644000076500000240000001752000000000000020262 0ustar00mdartiailhstaff00000000000000/*----------------------------------------------------------------------------- | Copyright (c) 2014-2020, Nucleic | | Distributed under the terms of the BSD 3-Clause License. | | The full license is in the file LICENSE, distributed with this software. |----------------------------------------------------------------------------*/ #pragma once #include #include #include "defines.h" namespace cppy { template inline T* incref( T* ob ) { Py_INCREF( ob ); return ob; } template inline T* xincref( T* ob ) { Py_XINCREF( ob ); return ob; } template inline T* decref( T* ob ) { Py_DECREF( ob ); return ob; } template inline T* xdecref( T* ob ) { Py_XDECREF( ob ); return ob; } template inline void clear( T** ob ) { T* temp = *ob; *ob = 0; Py_XDECREF( temp ); } template inline void replace( T** src, T* ob ) { T* temp = *src; *src = ob; Py_XINCREF( ob ); Py_XDECREF( temp ); } class ptr { public: ptr() : m_ob( 0 ) { } ptr( const ptr& other ) : m_ob( cppy::xincref( other.get() ) ) { } ptr( PyObject* ob, bool incref = false ) : m_ob( incref ? cppy::xincref( ob ) : ob ) { } ~ptr() { PyObject* temp = m_ob; m_ob = 0; Py_XDECREF( temp ); } ptr& operator=( PyObject* other ) { PyObject* temp = m_ob; m_ob = other; Py_XDECREF( temp ); return *this; } ptr& operator=( const ptr& other ) { PyObject* temp = m_ob; m_ob = other.get(); Py_XINCREF( m_ob ); Py_XDECREF( temp ); return *this; } PyObject* get() const { return m_ob; } void set( PyObject* ob, bool incref = false ) { PyObject* temp = m_ob; m_ob = incref ? cppy::xincref( ob ) : ob; Py_XDECREF( temp ); } void set( const ptr& other ) { PyObject* temp = m_ob; m_ob = other.get(); Py_XINCREF( m_ob ); Py_XDECREF( temp ); } PyObject* release() { PyObject* temp = m_ob; m_ob = 0; return temp; } operator void*() const { return static_cast( m_ob ); } bool is_none() const { return m_ob == Py_None; } bool is_true() const { return m_ob == Py_True; } bool is_false() const { return m_ob == Py_False; } bool is_bool() const { return is_true() || is_false(); } bool is_int() const { return PyLong_Check( m_ob ) != 0; } bool is_float() const { return PyFloat_Check( m_ob ) != 0; } bool is_list() const { return PyList_Check( m_ob ) != 0; } bool is_dict() const { return PyDict_Check( m_ob ) != 0; } bool is_set() const { return PySet_Check( m_ob ) != 0; } bool is_bytes() const { return PyBytes_Check( m_ob ) != 0; } bool is_str() const { return PyUnicode_Check( m_ob ) != 0; } bool is_unicode() const { return PyUnicode_Check( m_ob ) != 0; } bool is_callable() const { return PyCallable_Check( m_ob ) != 0; } bool is_iter() const { return PyIter_Check( m_ob ) != 0; } bool is_type( PyTypeObject* cls ) const { return PyObject_TypeCheck( m_ob, cls ) != 0; } int is_truthy() const { return PyObject_IsTrue( m_ob ); } int is_instance( PyObject* cls ) const { return PyObject_IsInstance( m_ob, cls ); } int is_instance( const ptr& cls ) const { return is_instance( cls.get() ); } int is_subclass( PyObject* cls ) const { return PyObject_IsSubclass( m_ob, cls ); } int is_subclass( const ptr& cls ) const { return is_subclass( cls.get() ); } PyObject* iter() const { return PyObject_GetIter( m_ob ); } PyObject* next() const { return PyIter_Next( m_ob ); } PyObject* repr() const { return PyObject_Repr( m_ob ); } PyObject* str() const { return PyObject_Str( m_ob ); } PyObject* bytes() const { return PyObject_Bytes( m_ob ); } PyObject* unicode() const { return PyObject_Str( m_ob ); } Py_ssize_t length() const { return PyObject_Length( m_ob ); } PyTypeObject* type() const { return m_ob->ob_type; } int richcmp( PyObject* other, int opid ) const { return PyObject_RichCompareBool( m_ob, other, opid ); } int richcmp( const ptr& other, int opid ) const { return richcmp( other.get(), opid ); } Py_hash_t hash() const { return PyObject_Hash( m_ob ); } bool hasattr( PyObject* attr ) const { return PyObject_HasAttr( m_ob, attr ) == 1; } bool hasattr( const ptr& attr ) const { return hasattr( attr.get() ); } bool hasattr( const char* attr ) const { return PyObject_HasAttrString( m_ob, attr ) == 1; } bool hasattr( const std::string& attr ) const { return hasattr( attr.c_str() ); } PyObject* getattr( PyObject* attr ) const { return PyObject_GetAttr( m_ob, attr ); } PyObject* getattr( const ptr& attr ) const { return getattr( attr.get() ); } PyObject* getattr( const char* attr ) const { return PyObject_GetAttrString( m_ob, attr ); } PyObject* getattr( const std::string& attr ) const { return getattr( attr.c_str() ); } bool setattr( PyObject* attr, PyObject* value ) const { return PyObject_SetAttr( m_ob, attr, value ) == 0; } bool setattr( const ptr& attr, PyObject* value ) const { return setattr( attr.get(), value ); } bool setattr( PyObject* attr, const ptr& value ) const { return setattr( attr, value.get() ); } bool setattr( const ptr& attr, const ptr& value ) const { return setattr( attr.get(), value.get() ); } bool setattr( const char* attr, PyObject* value ) const { return PyObject_SetAttrString( m_ob, attr, value ) == 0; } bool setattr( const char* attr, const ptr& value ) const { return setattr( attr, value.get() ); } bool setattr( const std::string& attr, PyObject* value ) const { return setattr( attr.c_str(), value ); } bool setattr( const std::string& attr, const ptr& value ) const { return setattr( attr.c_str(), value.get() ); } bool delattr( PyObject* attr ) const { return PyObject_DelAttr( m_ob, attr ) == 0; } bool delattr( const ptr& attr ) const { return delattr( attr.get() ); } bool delattr( const char* attr ) const { return PyObject_DelAttrString( m_ob, attr ) == 0; } bool delattr( const std::string& attr ) const { return delattr( attr.c_str() ); } PyObject* getitem( PyObject* key ) const { return PyObject_GetItem( m_ob, key ); } PyObject* getitem( const ptr& key ) const { return getitem( key.get() ); } bool setitem( PyObject* key, PyObject* value ) const { return PyObject_SetItem( m_ob, key, value ) == 0; } bool setitem( const ptr& key, PyObject* value ) const { return setitem( key.get(), value ); } bool setitem( PyObject* key, const ptr& value ) const { return setitem( key, value.get() ); } bool setitem( const ptr& key, const ptr& value ) const { return setitem( key.get(), value.get() ); } bool delitem( PyObject* key ) { return PyObject_DelItem( m_ob, key ) == 0; } bool delitem( const ptr& key ) { return delitem( key.get() ); } PyObject* call( PyObject* args, PyObject* kwargs = 0 ) const { return PyObject_Call( m_ob, args, kwargs ); } PyObject* call( const ptr& args ) const { return call( args.get() ); } PyObject* call( const ptr& args, const ptr& kwargs ) const { return call( args.get(), kwargs.get() ); } PyObject* call( const ptr& args, PyObject* kwargs ) const { return call( args.get(), kwargs ); } PyObject* call( PyObject* args, const ptr& kwargs ) const { return call( args, kwargs.get() ); } protected: PyObject* m_ob; }; inline bool operator!=( const ptr& lhs, const ptr& rhs ) { return lhs.get() != rhs.get(); } inline bool operator!=( PyObject* lhs, const ptr& rhs ) { return lhs != rhs.get(); } inline bool operator!=( const ptr& lhs, PyObject* rhs ) { return lhs.get() != rhs; } inline bool operator==( const ptr& lhs, const ptr& rhs ) { return lhs.get() == rhs.get(); } inline bool operator==( PyObject* lhs, const ptr& rhs ) { return lhs == rhs.get(); } inline bool operator==( const ptr& lhs, PyObject* rhs ) { return lhs.get() == rhs; } } // namespace cppy ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1585174471.613258 cppy-1.1.0/cppy.egg-info/0000755000076500000240000000000000000000000016373 5ustar00mdartiailhstaff00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1585174471.0 cppy-1.1.0/cppy.egg-info/PKG-INFO0000644000076500000240000000131500000000000017470 0ustar00mdartiailhstaff00000000000000Metadata-Version: 1.0 Name: cppy Version: 1.1.0 Summary: C++ headers for C extension development Home-page: https://github.com/nucleic/cppy Author: The Nucleic Development Team Author-email: sccolbert@gmail.com License: UNKNOWN Description: cppy ==== .. image:: https://travis-ci.org/nucleic/cppy.svg?branch=master :target: https://travis-ci.org/nucleic/cppy A small C++ header library which makes it easier to write Python extension modules. The primary feature is a PyObject smart pointer which automatically handles reference counting and provides convenience methods for performing common object operations. Platform: UNKNOWN ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1585174471.0 cppy-1.1.0/cppy.egg-info/SOURCES.txt0000644000076500000240000000072500000000000020263 0ustar00mdartiailhstaff00000000000000LICENSE MANIFEST.in README.rst releasenotes.rst setup.py cppy/__init__.py cppy.egg-info/PKG-INFO cppy.egg-info/SOURCES.txt cppy.egg-info/dependency_links.txt cppy.egg-info/top_level.txt cppy/include/cppy/cppy.h cppy/include/cppy/defines.h cppy/include/cppy/errors.h cppy/include/cppy/ptr.h docs/Makefile docs/make.bat docs/source/conf.py docs/source/errors.rst docs/source/index.rst docs/source/installation.rst docs/source/pointer.rst tests/test_getting_include_dir.py././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1585174471.0 cppy-1.1.0/cppy.egg-info/dependency_links.txt0000644000076500000240000000000100000000000022441 0ustar00mdartiailhstaff00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1585174471.0 cppy-1.1.0/cppy.egg-info/top_level.txt0000644000076500000240000000000500000000000021120 0ustar00mdartiailhstaff00000000000000cppy ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1585174471.6160915 cppy-1.1.0/docs/0000755000076500000240000000000000000000000014656 5ustar00mdartiailhstaff00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1579137253.0 cppy-1.1.0/docs/Makefile0000644000076500000240000000111000000000000016307 0ustar00mdartiailhstaff00000000000000# Minimal makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build SOURCEDIR = source BUILDDIR = build # Put it first so that "make" without argument is like "make help". help: @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) .PHONY: help Makefile # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1579137253.0 cppy-1.1.0/docs/make.bat0000644000076500000240000000142700000000000016267 0ustar00mdartiailhstaff00000000000000@ECHO OFF pushd %~dp0 REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set SOURCEDIR=source set BUILDDIR=build if "%1" == "" goto help %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( echo. echo.The 'sphinx-build' command was not found. Make sure you have Sphinx echo.installed, then set the SPHINXBUILD environment variable to point echo.to the full path of the 'sphinx-build' executable. Alternatively you echo.may add the Sphinx directory to PATH. echo. echo.If you don't have Sphinx installed, grab it from echo.http://sphinx-doc.org/ exit /b 1 ) %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% goto end :help %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% :end popd ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1585174471.6184216 cppy-1.1.0/docs/source/0000755000076500000240000000000000000000000016156 5ustar00mdartiailhstaff00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1579137253.0 cppy-1.1.0/docs/source/conf.py0000644000076500000240000001252400000000000017461 0ustar00mdartiailhstaff00000000000000# -*- coding: utf-8 -*- # # Configuration file for the Sphinx documentation builder. # # This file does only contain a selection of the most common options. For a # full list see the documentation: # http://www.sphinx-doc.org/en/master/config # -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # # import os # import sys # sys.path.insert(0, os.path.abspath('.')) # -- Project information ----------------------------------------------------- project = 'cppy' copyright = '2019, Nucleic team' author = 'Nucleic team' # The short X.Y version version = '' # The full version, including alpha/beta/rc tags release = '1.1.0' # -- General configuration --------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. # # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.intersphinx', 'sphinx.ext.mathjax', 'sphinx.ext.viewcode', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The master toctree document. master_doc = 'index' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. exclude_patterns = [] # The name of the Pygments (syntax highlighting) style to use. pygments_style = None # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'sphinx_rtd_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # # html_theme_options = {} # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Custom sidebar templates, must be a dictionary that maps document names # to template names. # # The default sidebars (for documents that don't match any pattern) are # defined by theme itself. Builtin themes are using these templates by # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', # 'searchbox.html']``. # # html_sidebars = {} # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. htmlhelp_basename = 'cppydoc' # -- Options for LaTeX output ------------------------------------------------ latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # # 'preamble': '', # Latex figure (float) alignment # # 'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ (master_doc, 'cppy.tex', 'cppy Documentation', 'Nucleic team', 'manual'), ] # -- Options for manual page output ------------------------------------------ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, 'cppy', 'cppy Documentation', [author], 1) ] # -- Options for Texinfo output ---------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'cppy', 'cppy Documentation', author, 'cppy', 'One line description of project.', 'Miscellaneous'), ] # -- Options for Epub output ------------------------------------------------- # Bibliographic Dublin Core info. epub_title = project # The unique identifier of the text. This can be a ISBN number # or the project homepage. # # epub_identifier = '' # A unique identification for the text. # # epub_uid = '' # A list of files that should not be packed into the epub file. epub_exclude_files = ['search.html'] # -- Extension configuration ------------------------------------------------- # -- Options for intersphinx extension --------------------------------------- # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'https://docs.python.org/': None}././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1579137253.0 cppy-1.1.0/docs/source/errors.rst0000644000076500000240000000172100000000000020225 0ustar00mdartiailhstaff00000000000000Error reporting =============== In addition to `cppy::ptr`, cppy provides a set a convenience function for reporting errors which all return a NULL pointer allowing them to be used as follows: .. code:: c++ PyObject* function( PyObject* obj ) { cppy::ptr obj_ptr( cppy::incref( obj ) ); if( !obj_ptr.is_bool() ) return type_error( obj_ptr.get(), 'bool' ) return obj_ptr.get() } Functions --------- Functions taking two arguments provide sensible pre-formated error messages. .. code:: c++ inline PyObject* system_error( const char* message ) inline PyObject* type_error( const char* message ) inline PyObject* type_error( PyObject* ob, const char* expected ) inline PyObject* value_error( const char* message ) inline PyObject* runtime_error( const char* message ) inline PyObject* attribute_error( const char* message ) inline PyObject* attribute_error( PyObject* ob, const char* attr ) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1579137253.0 cppy-1.1.0/docs/source/index.rst0000644000076500000240000000116300000000000020020 0ustar00mdartiailhstaff00000000000000.. cppy documentation master file, created by sphinx-quickstart on Wed Mar 27 22:37:56 2019. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Welcome to cppy's documentation! ================================ Cpppy is a small C++ header library which makes it easier to write Python extension modules. The primary feature is a PyObject smart pointer which automatically handles reference counting and provides convenience methods for performing common object operations. .. toctree:: :maxdepth: 2 installation.rst pointer.rst errors.rst ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1579137253.0 cppy-1.1.0/docs/source/installation.rst0000644000076500000240000000366400000000000021422 0ustar00mdartiailhstaff00000000000000Installation and use with setuptools ==================================== Since cppy is nothing else than a collection of header that are only compiled when used, installing it is extremely straightforward using pip:: $ pip install cppy If you want to run the development version, you can install directly from Github:: $ pip install https://github.com/nucleic/cppy Using cppy in an extensions --------------------------- To use cppy in your extension (written in C++), you simply need to include it. .. code:: c++ #include Cppy includes Python.h so when including cppy.h you do not need to also include Python.h. Every functions, classes exposed by cppy are stored in the `cppy` namespace. .. code:: c++ cppy::ptr obj_ptr( PyUnicode_FromString("test") ) Use with setuptools ------------------- Cppy is only needed during the installation step of the projects using it. The following example setup.py script illustrates how to use cppy without requiring it to be installed before `setup.py` is run. .. code:: python from setuptools import setup, Extension from setuptools.command.build_ext import build_ext ext_modules = [ Extension( 'project', ['module.cpp], include_dirs=['.'], language='c++', ), ] class BuildExt(build_ext): def build_extensions(self): # Delayed import of cppy to let setup_requires install it if # necessary import cppy ct = self.compiler.compiler_type for ext in self.extensions: # cppy.get_include() collect the path of the header files ext.include_dirs.insert(0, cppy.get_include()) build_ext.build_extensions(self) setup( name='project', python_requires='>=3.5', setup_requires=['cppy'], ext_modules=ext_modules, cmdclass={'build_ext': BuildExt}, ) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1579137253.0 cppy-1.1.0/docs/source/pointer.rst0000644000076500000240000001730500000000000020376 0ustar00mdartiailhstaff00000000000000Cppy smart pointer ================== CPython relies on reference counting to manage object lifetime. A large pitfall when writing C-extension is to properly handle increfing and decrefing the reference count. Cppy aims at simplifying this process by providing a smart pointer class. Before diving into the details of it helps lets start a CPython reference counting crash-course. CPython reference counting crash course --------------------------------------- Each object allocated by Python has a reference count, indicating how many times this object is 'used'. When the reference count of an object goes to zero, it is de-allocated. Outside of C extension, one does not need to manage the reference count manually. When a function part of Python C-API returns a Python object, it returns a pointer to it. At the time at which the function returns, the referenced object is live and its reference count is above zero. Depending of the function, you do not have the same responsibility with respect to that object reference count: - Owned references: Most functions return a `new` reference which means that you are responsible for decrefing the object reference count when you are done with it (basically the function increfed the object reference count before returning). In this situation you own a reference. - Borrowed reference: Some functions (`PyList_GetItem`, `PyTuple_GetItem`) do not incref the object count before returning. In that case, you have only a borrowed reference, you are not responsible for decrefing the object reference count. Borrowed references allow to avoid the cost of increfing/decrefing which is nice. However since you do not own the reference, if the object referenced is removed from its owner (list, tuple for the above two mentioned functions) it may just disappear and your reference becomes invalid. This can cause issues. If the object should outlive the container, or the time it will spend in the container you have to incref it manually. Lets now discuss the convention when calling a function. When calling a function, the caller is expected to own a reference to each of the arguments passed to the callee. The callee does not own the references, it only borrows them. As a consequence, it should not decref the reference and if it needs to store the object, in for example a C structure, it should incref it. Note that this does not apply in general to Python container since those are manipulated using functions that take care of it. There are however some exceptions that steals a reference, meaning that you are not the owner of the reference after the call. `PyList_SetItem`, for example, steal references. An easy way to get reference count wrong is forgetting to decref some intermediate object before leaving a function. This is particularly true if the function has some early exit point because an exception should be raised. A good practice is to have a single exit point, however it is not always possible/practical and even like this it is possible to miss references, this is typically where cppy can help. This is a very brief introduction to reference counting. You can read a bit more in the official `Python documentation`_ and in the `Python API`_ documentation. .. _Python documentation: https://docs.python.org/3/c-api/intro.html#objects-types-and-reference-counts .. _Python API: https://docs.python.org/3/c-api/refcounting.html Cppy smart pointer class ------------------------ Cppy smart pointer (`cppy::ptr`) can be initialized with a pointer to a Python object as follows: .. code:: c++ cppy::ptr obj_ptr( PyUnicode_FromString("test") ) When created, the class assume that you own the reference, if it is not the case you should incref it first: .. code:: c++ PyObject* function( PyObject* obj ) { cppy::ptr obj_ptr( cppy::incref( obj ) ); cppy::ptr obj_ptr2( obj, true ); } .. note:: Cppy provides convenient inline function for common reference manipulation: - `cppy::incref`, `cppy::xincref`, `cppy::decref`, `cppy::xdecref` use the the similarly named Python macros and return the input value. - `cppy::clear`, `cppy::replace` are similar but return void. You can also initialize a `cppy::ptr` from another `cppy::ptr` in which case the reference count will always be incremented. The main advantage provided by `cppy::ptr` is that it implements a destructor that will be invoked automatically by the c++ runtime when the `cppy::ptr` goes out of scope. The destructor will decref the reference for you. As a consequence you can be sure that your reference you always be decremented when you leave the function. Sometimes, however, that is not what you want, because you want to return the reference the `cppy::ptr` manage. You can request the `cppy::ptr` to give back the reference using its `release` method. Lets illustrate on a tiny example: .. code:: c++ PyObject* function( PyObject* obj ) { cppy::ptr repr_ptr( PyObject_Repr( obj ) ); return repr_ptr.release(); } Function which are part of Python C-API are not aware of of `cppy::ptr` and when calling them you need to provide the original `PyObject*`. To access, you simply need to call the `get` method of the `cppy::ptr` object. .. code:: c++ PyObject* function( PyObject* obj ) { cppy::ptr l_ptr( PyList_New() ); if( PyList_Append( l_ptr.get(), obj ) != 0 ) return 0; return l_ptr.release(); } Here we see that because we use `cppy::ptr` to manage the list, we do not have to worry about decrefing the reference if an exception occurs, the runtime will do it for us. If no exception occurs, we stop managing the reference and we are good. Using cppy does not eliminate all the pitfalls of writing C-extensions. For example if you release too early (for example when passing the object to a function that may fail), you can still leak references. However it does alleviate some of the complexity. Cppy::ptr methods ----------------- All methods that takes a `PyObject*` can also accept a `cppy::ptr`. Most names should be self-explanatory, and apart from the is\_ methods most of them rely on the PyObject\_ functions similarly named: .. code:: c++ bool is_none() const bool is_true() const bool is_false() const bool is_bool() const bool is_int() const bool is_float() const bool is_list() const bool is_dict() const bool is_set() const bool is_bytes() const bool is_str() const bool is_unicode() const bool is_callable() const bool is_iter() const bool is_type( PyTypeObject* cls ) const int is_truthy() const int is_instance( PyObject* cls ) const int is_subclass( PyObject* cls ) const PyObject* iter() const PyObject* next() const PyObject* repr() const PyObject* str() const PyObject* bytes() const PyObject* unicode() const Py_ssize_t length() const PyTypeObject* type() const int richcmp( PyObject* other, int opid ) const long hash() const bool hasattr( PyObject* attr ) const bool hasattr( const char* attr ) const bool hasattr( const std::string& attr ) const PyObject* getattr( PyObject* attr ) const PyObject* getattr( const char* attr ) const PyObject* getattr( const std::string& attr ) const bool setattr( PyObject* attr, PyObject* value ) const bool setattr( const char* attr, PyObject* value ) const bool setattr( const std::string& attr, PyObject* value ) const bool delattr( PyObject* attr ) const bool delattr( const char* attr ) const bool delattr( const std::string& attr ) const PyObject* getitem( PyObject* key ) const bool setitem( PyObject* key, PyObject* value ) const bool delitem( PyObject* key ) PyObject* call( PyObject* args, PyObject* kwargs = 0 ) const ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1585174324.0 cppy-1.1.0/releasenotes.rst0000644000076500000240000000061500000000000017153 0ustar00mdartiailhstaff00000000000000Cppy Release Notes =================== 1.1.0 - unreleased ------------------ - drop Python 2 support PR #3 - add documentation and tests PR #3 - add cast_py_tp_doc to cast "cleanly" to void* for use in PyType_Slot 1.0.2 - 09/28/2014 ------------------ - update license header 1.0.1 - 09/28/2014 ------------------ - fix Python 3 int check 1.0.0 - 09/24/2014 ------------------ - first release ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1585174471.6206498 cppy-1.1.0/setup.cfg0000644000076500000240000000004600000000000015547 0ustar00mdartiailhstaff00000000000000[egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1579137253.0 cppy-1.1.0/setup.py0000644000076500000240000000147500000000000015447 0ustar00mdartiailhstaff00000000000000#------------------------------------------------------------------------------ # Copyright (c) 2014-2019, Nucleic # # Distributed under the terms of the BSD 3-Clause License. # # The full license is in the file LICENSE, distributed with this software. #------------------------------------------------------------------------------ from setuptools import setup # Before releasing the version needs to be updated in: # - setup.py # - cppy/__init__.py # - docs/source/conf.py setup( name='cppy', version='1.1.0', author='The Nucleic Development Team', author_email='sccolbert@gmail.com', url='https://github.com/nucleic/cppy', description='C++ headers for C extension development', long_description=open('README.rst').read(), packages=['cppy'], package_data={'cppy': ['include/cppy/*.h']}, ) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1585174471.6192002 cppy-1.1.0/tests/0000755000076500000240000000000000000000000015070 5ustar00mdartiailhstaff00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1579137253.0 cppy-1.1.0/tests/test_getting_include_dir.py0000644000076500000240000000101600000000000022501 0ustar00mdartiailhstaff00000000000000#------------------------------------------------------------------------------ # Copyright (c) 2014-2019, Nucleic # # Distributed under the terms of the BSD 3-Clause License. # # The full license is in the file LICENSE, distributed with this software. #------------------------------------------------------------------------------ """Test getting the include directory. """ def test_getting_include_directory(): """Test getting the include directory. """ from cppy import get_include assert get_include()