# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['refcount']

package_data = \
{'': ['*']}

install_requires = \
['cffi>=1.11.5,<2.0.0', 'typing-extensions>=4.3.0,<5.0.0']

setup_kwargs = {
    'name': 'refcount',
    'version': '1.1.1',
    'description': 'Python classes for reference counting',
    'long_description': '# refcount - Python classes for reference counting\n\n[![license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/csiro-hydroinformatics/pyrefcount/blob/master/LICENSE.txt) ![status](https://img.shields.io/badge/status-stable-green.svg) [![Documentation Status](https://readthedocs.org/projects/pyrefcount/badge/?version=latest)](https://pyrefcount.readthedocs.io/en/latest/?badge=latest) [![codecov](https://codecov.io/gh/csiro-hydroinformatics/pyrefcount/branch/master/graph/badge.svg?token=ZBBFq3ncAq)](https://codecov.io/gh/csiro-hydroinformatics/pyrefcount) master: [![Python package](https://github.com/csiro-hydroinformatics/pyrefcount/actions/workflows/build-matrix.yml/badge.svg?branch=master)](https://github.com/csiro-hydroinformatics/pyrefcount/actions/workflows/build-matrix.yml) testing: [![Python package](https://github.com/csiro-hydroinformatics/pyrefcount/actions/workflows/build-matrix.yml/badge.svg?branch=testing)](https://github.com/csiro-hydroinformatics/pyrefcount/actions/workflows/build-matrix.yml)\n\n\n![Reference counted native handles](./docs/img/refcount-principles.png "Reference counted native handles")\n\nThis package is primarily for managing resources in native libraries, written for instance in C++, from Python. While it boils down to "simply" maintaining a set of counters, **it is deceptively complicated to do so properly** and not end up with memory leaks or crashes. This package offers structured options for reliably managing external native resources. Surprisingly I could not locate an existing package doing just what I needed. Other use cases requiring reference counting, aside from native library resources, may benefit from reusing and extending classes in `refcount`.\n\n`refcount` ( >=0.7) includes classes using [cffi](https://cffi.readthedocs.io/). Other low-level interoperability mechanisms may well be added in the future.\n\n## License\n\nMIT (see [License.txt](https://github.com/csiro-hydroinformatics/pyrefcount/blob/master/LICENSE.txt))\n\n## Documentation\n\nHosted at [refcount via readthedocs.io](https://pyrefcount.readthedocs.io/en/latest/?badge=latest)\n\n## Source code\n\nThe code repository is on [GitHub](https://github.com/csiro-hydroinformatics/pyrefcount).\n\n## Installation\n\n### conda-forge\n\nUsing `conda` or `mamba`:\n\n```sh\nmamba install -c conda-forge refcount\n```\n\n### pypi\n\n```sh\npip install refcount\n```\n\n### From source (development)\n\n```sh\npip install -r requirements.txt\npip install -e .\n```\n\n## Sample use\n\nThe following example is based on one of the unit tests.\n\nSay we have a C++ library with objects and a C API:\n\n```C++\n#define TEST_DOG_PTR  testnative::dog*\n#define TEST_OWNER_PTR  testnative::owner*\n#define TEST_COUNTED_PTR  testnative::reference_counter*\n\ntestnative::dog* create_dog();\ntestnative::owner* create_owner(testnative::dog* d);\nvoid say_walk(testnative::owner* owner);\nvoid release(testnative::reference_counter* obj);\n// etc.\n```\n\nFrom the outside of the library the API is exported with opaque pointers `void*` (C structs pointers and native C99 types could be handled too).\n\n```C++\nvoid* create_dog();\nvoid* create_owner(void* d);\nvoid say_walk(void* owner);\nvoid release(void* obj);\n// etc.\n```\n\nStarting with the end in mind, from Python we want an API hiding the low level details close to the C API, in particular avoiding managing native memory via `release` C API calls, piggybacking the python GC instead.\n\n```python\ndog = Dog()\nowner = DogOwner(dog)\nowner.say_walk()\nprint(dog.position)\ndog = None # the "native dog" is still alive though, as the owner incremented the ref count\nowner = None\n```\n\nThis is doable with `refcount` and the `cffi` package. One possible design is:\n\n```python\nut_ffi = cffi.FFI()\n\nut_ffi.cdef(\'extern void* create_dog();\')\nut_ffi.cdef(\'extern void* create_owner( void* d);\')\nut_ffi.cdef(\'extern void say_walk( void* owner);\')\nut_ffi.cdef(\'extern void release( void* obj);\')\n# etc.\n\nut_dll = ut_ffi.dlopen(\'c:/path/to/test_native_library.dll\', 1) # Lazy loading\n\nclass CustomCffiNativeHandle(CffiNativeHandle):\n    def __init__(self, pointer, prior_ref_count = 0):\n        super(CustomCffiNativeHandle, self).__init__(pointer, type_id=\'\', prior_ref_count = prior_ref_count)\n\n    def _release_handle(self) -> bool:\n        ut_dll.release(self.get_handle())\n        return True\n\nclass Dog(CustomCffiNativeHandle):\n    def __init__(self, pointer = None):\n        if pointer is None:\n            pointer = ut_dll.create_dog()\n        super(Dog, self).__init__(pointer)\n    # etc.\n\nclass DogOwner(CustomCffiNativeHandle):\n\n    def __init__(self, dog):\n        super(DogOwner, self).__init__(None)\n        self._set_handle(ut_dll.create_owner(dog.get_handle()))\n        self.dog = dog\n        self.dog.add_ref() # Do note this important reference increment\n\n    def say_walk(self):\n        ut_dll.say_walk(self.get_handle())\n\n    def _release_handle(self) -> bool:\n        super(DogOwner, self)._release_handle()\n        # super(DogOwner, self)._release_handle()\n        self.dog.release()\n        return True\n```\n\n## Related work\n\n### Ancestry, acknowledgements\n\nThis python package `refcount` actually spawned from prior work for interoperability between C++, R and .NET ([R.NET](https://github.com/rdotnet/rdotnet))\n\n`refcount` features using `cffi` were also significantly informed by Kevin Plastow\'s [work](https://search.informit.com.au/documentSummary;dn=823898220073899;res=IELENG) while he was at the Australian Bureau of Meteorology; this contribution is gratefully acknowledged.\n\nIn you have native interop needs you may also want to look at:\n\n* the nuget package [dynamic-interop-dll](https://github.com/rdotnet/dynamic-interop-dll) for .NET/native interop.\n* a set of mostly c++ software [tools for interop with C/C++](https://github.com/csiro-hydroinformatics/c-interop)\n* a C# library for [generating interop glue code on top of C API glue code](https://github.com/csiro-hydroinformatics/c-api-wrapper-generation).\n\n### Other python packages\n\n`refcount` was created in part because no existing prior (Python) work could quite fit the need. There are however packages that may better address your particular need:\n\n* [infi.pyutils](https://pypi.org/project/infi.pyutils/) contains a reference counting class.\n',
    'author': 'J-M',
    'author_email': 'jean-michel.perraud@csiro.au',
    'maintainer': None,
    'maintainer_email': None,
    'url': None,
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.7,<4.0',
}


setup(**setup_kwargs)
