%global _empty_manifest_terminate_build 0
Name: python-cymem
Version: 2.0.7
Release: 1
Summary: Manage calls to calloc/free through Cython
License: MIT
URL: https://github.com/explosion/cymem
Source0: https://mirrors.nju.edu.cn/pypi/web/packages/b0/d3/50c90dd821e44ad289653f0029d1690fca82f90df293e77e21443f5ea4fc/cymem-2.0.7.tar.gz
%description
# cymem: A Cython Memory Helper
cymem provides two small memory-management helpers for Cython. They make it
easy to tie memory to a Python object's life-cycle, so that the memory is freed
when the object is garbage collected.
[![Azure Pipelines](https://img.shields.io/azure-devops/build/explosion-ai/public/2/master.svg?logo=azure-pipelines&style=flat-square)](https://dev.azure.com/explosion-ai/public/_build?definitionId=2)
[![pypi Version](https://img.shields.io/pypi/v/cymem.svg?style=flat-square&logo=pypi&logoColor=white)](https://pypi.python.org/pypi/cymem)
[![conda Version](https://img.shields.io/conda/vn/conda-forge/cymem.svg?style=flat-square&logo=conda-forge&logoColor=white)](https://anaconda.org/conda-forge/cymem)
[![Python wheels](https://img.shields.io/badge/wheels-%E2%9C%93-4c1.svg?longCache=true&style=flat-square&logo=python&logoColor=white)](https://github.com/explosion/wheelwright/releases)
## Overview
The most useful is `cymem.Pool`, which acts as a thin wrapper around the calloc
function:
```python
from cymem.cymem cimport Pool
cdef Pool mem = Pool()
data1 = mem.alloc(10, sizeof(int))
data2 = mem.alloc(12, sizeof(float))
```
The `Pool` object saves the memory addresses internally, and frees them when the
object is garbage collected. Typically you'll attach the `Pool` to some cdef'd
class. This is particularly handy for deeply nested structs, which have
complicated initialization functions. Just pass the `Pool` object into the
initializer, and you don't have to worry about freeing your struct at all —
all of the calls to `Pool.alloc` will be automatically freed when the `Pool`
expires.
## Installation
Installation is via [pip](https://pypi.python.org/pypi/pip), and requires [Cython](http://cython.org). Before installing, make sure that your `pip`, `setuptools` and `wheel` are up to date.
```bash
pip install -U pip setuptools wheel
pip install cymem
```
## Example Use Case: An array of structs
Let's say we want a sequence of sparse matrices. We need fast access, and
a Python list isn't performing well enough. So, we want a C-array or C++
vector, which means we need the sparse matrix to be a C-level struct — it
can't be a Python class. We can write this easily enough in Cython:
```python
"""Example without Cymem
To use an array of structs, we must carefully walk the data structure when
we deallocate it.
"""
from libc.stdlib cimport calloc, free
cdef struct SparseRow:
size_t length
size_t* indices
double* values
cdef struct SparseMatrix:
size_t length
SparseRow* rows
cdef class MatrixArray:
cdef size_t length
cdef SparseMatrix** matrices
def __cinit__(self, list py_matrices):
self.length = 0
self.matrices = NULL
def __init__(self, list py_matrices):
self.length = len(py_matrices)
self.matrices = calloc(len(py_matrices), sizeof(SparseMatrix*))
for i, py_matrix in enumerate(py_matrices):
self.matrices[i] = sparse_matrix_init(py_matrix)
def __dealloc__(self):
for i in range(self.length):
sparse_matrix_free(self.matrices[i])
free(self.matrices)
cdef SparseMatrix* sparse_matrix_init(list py_matrix) except NULL:
sm = calloc(1, sizeof(SparseMatrix))
sm.length = len(py_matrix)
sm.rows = calloc(sm.length, sizeof(SparseRow))
cdef size_t i, j
cdef dict py_row
cdef size_t idx
cdef double value
for i, py_row in enumerate(py_matrix):
sm.rows[i].length = len(py_row)
sm.rows[i].indices = calloc(sm.rows[i].length, sizeof(size_t))
sm.rows[i].values = calloc(sm.rows[i].length, sizeof(double))
for j, (idx, value) in enumerate(py_row.items()):
sm.rows[i].indices[j] = idx
sm.rows[i].values[j] = value
return sm
cdef void* sparse_matrix_free(SparseMatrix* sm) except *:
cdef size_t i
for i in range(sm.length):
free(sm.rows[i].indices)
free(sm.rows[i].values)
free(sm.rows)
free(sm)
```
We wrap the data structure in a Python ref-counted class at as low a level as
we can, given our performance constraints. This allows us to allocate and free
the memory in the `__cinit__` and `__dealloc__` Cython special methods.
However, it's very easy to make mistakes when writing the `__dealloc__` and
`sparse_matrix_free` functions, leading to memory leaks. cymem prevents you from
writing these deallocators at all. Instead, you write as follows:
```python
"""Example with Cymem.
Memory allocation is hidden behind the Pool class, which remembers the
addresses it gives out. When the Pool object is garbage collected, all of
its addresses are freed.
We don't need to write MatrixArray.__dealloc__ or sparse_matrix_free,
eliminating a common class of bugs.
"""
from cymem.cymem cimport Pool
cdef struct SparseRow:
size_t length
size_t* indices
double* values
cdef struct SparseMatrix:
size_t length
SparseRow* rows
cdef class MatrixArray:
cdef size_t length
cdef SparseMatrix** matrices
cdef Pool mem
def __cinit__(self, list py_matrices):
self.mem = None
self.length = 0
self.matrices = NULL
def __init__(self, list py_matrices):
self.mem = Pool()
self.length = len(py_matrices)
self.matrices = self.mem.alloc(self.length, sizeof(SparseMatrix*))
for i, py_matrix in enumerate(py_matrices):
self.matrices[i] = sparse_matrix_init(self.mem, py_matrix)
cdef SparseMatrix* sparse_matrix_init_cymem(Pool mem, list py_matrix) except NULL:
sm = mem.alloc(1, sizeof(SparseMatrix))
sm.length = len(py_matrix)
sm.rows = mem.alloc(sm.length, sizeof(SparseRow))
cdef size_t i, j
cdef dict py_row
cdef size_t idx
cdef double value
for i, py_row in enumerate(py_matrix):
sm.rows[i].length = len(py_row)
sm.rows[i].indices = mem.alloc(sm.rows[i].length, sizeof(size_t))
sm.rows[i].values = mem.alloc(sm.rows[i].length, sizeof(double))
for j, (idx, value) in enumerate(py_row.items()):
sm.rows[i].indices[j] = idx
sm.rows[i].values[j] = value
return sm
```
All that the `Pool` class does is remember the addresses it gives out. When the
`MatrixArray` object is garbage-collected, the `Pool` object will also be garbage
collected, which triggers a call to `Pool.__dealloc__`. The `Pool` then frees all of
its addresses. This saves you from walking back over your nested data structures
to free them, eliminating a common class of errors.
## Custom Allocators
Sometimes external C libraries use private functions to allocate and free objects,
but we'd still like the laziness of the `Pool`.
```python
from cymem.cymem cimport Pool, WrapMalloc, WrapFree
cdef Pool mem = Pool(WrapMalloc(priv_malloc), WrapFree(priv_free))
```
%package -n python3-cymem
Summary: Manage calls to calloc/free through Cython
Provides: python-cymem
BuildRequires: python3-devel
BuildRequires: python3-setuptools
BuildRequires: python3-pip
BuildRequires: python3-cffi
BuildRequires: gcc
BuildRequires: gdb
%description -n python3-cymem
# cymem: A Cython Memory Helper
cymem provides two small memory-management helpers for Cython. They make it
easy to tie memory to a Python object's life-cycle, so that the memory is freed
when the object is garbage collected.
[![Azure Pipelines](https://img.shields.io/azure-devops/build/explosion-ai/public/2/master.svg?logo=azure-pipelines&style=flat-square)](https://dev.azure.com/explosion-ai/public/_build?definitionId=2)
[![pypi Version](https://img.shields.io/pypi/v/cymem.svg?style=flat-square&logo=pypi&logoColor=white)](https://pypi.python.org/pypi/cymem)
[![conda Version](https://img.shields.io/conda/vn/conda-forge/cymem.svg?style=flat-square&logo=conda-forge&logoColor=white)](https://anaconda.org/conda-forge/cymem)
[![Python wheels](https://img.shields.io/badge/wheels-%E2%9C%93-4c1.svg?longCache=true&style=flat-square&logo=python&logoColor=white)](https://github.com/explosion/wheelwright/releases)
## Overview
The most useful is `cymem.Pool`, which acts as a thin wrapper around the calloc
function:
```python
from cymem.cymem cimport Pool
cdef Pool mem = Pool()
data1 = mem.alloc(10, sizeof(int))
data2 = mem.alloc(12, sizeof(float))
```
The `Pool` object saves the memory addresses internally, and frees them when the
object is garbage collected. Typically you'll attach the `Pool` to some cdef'd
class. This is particularly handy for deeply nested structs, which have
complicated initialization functions. Just pass the `Pool` object into the
initializer, and you don't have to worry about freeing your struct at all —
all of the calls to `Pool.alloc` will be automatically freed when the `Pool`
expires.
## Installation
Installation is via [pip](https://pypi.python.org/pypi/pip), and requires [Cython](http://cython.org). Before installing, make sure that your `pip`, `setuptools` and `wheel` are up to date.
```bash
pip install -U pip setuptools wheel
pip install cymem
```
## Example Use Case: An array of structs
Let's say we want a sequence of sparse matrices. We need fast access, and
a Python list isn't performing well enough. So, we want a C-array or C++
vector, which means we need the sparse matrix to be a C-level struct — it
can't be a Python class. We can write this easily enough in Cython:
```python
"""Example without Cymem
To use an array of structs, we must carefully walk the data structure when
we deallocate it.
"""
from libc.stdlib cimport calloc, free
cdef struct SparseRow:
size_t length
size_t* indices
double* values
cdef struct SparseMatrix:
size_t length
SparseRow* rows
cdef class MatrixArray:
cdef size_t length
cdef SparseMatrix** matrices
def __cinit__(self, list py_matrices):
self.length = 0
self.matrices = NULL
def __init__(self, list py_matrices):
self.length = len(py_matrices)
self.matrices = calloc(len(py_matrices), sizeof(SparseMatrix*))
for i, py_matrix in enumerate(py_matrices):
self.matrices[i] = sparse_matrix_init(py_matrix)
def __dealloc__(self):
for i in range(self.length):
sparse_matrix_free(self.matrices[i])
free(self.matrices)
cdef SparseMatrix* sparse_matrix_init(list py_matrix) except NULL:
sm = calloc(1, sizeof(SparseMatrix))
sm.length = len(py_matrix)
sm.rows = calloc(sm.length, sizeof(SparseRow))
cdef size_t i, j
cdef dict py_row
cdef size_t idx
cdef double value
for i, py_row in enumerate(py_matrix):
sm.rows[i].length = len(py_row)
sm.rows[i].indices = calloc(sm.rows[i].length, sizeof(size_t))
sm.rows[i].values = calloc(sm.rows[i].length, sizeof(double))
for j, (idx, value) in enumerate(py_row.items()):
sm.rows[i].indices[j] = idx
sm.rows[i].values[j] = value
return sm
cdef void* sparse_matrix_free(SparseMatrix* sm) except *:
cdef size_t i
for i in range(sm.length):
free(sm.rows[i].indices)
free(sm.rows[i].values)
free(sm.rows)
free(sm)
```
We wrap the data structure in a Python ref-counted class at as low a level as
we can, given our performance constraints. This allows us to allocate and free
the memory in the `__cinit__` and `__dealloc__` Cython special methods.
However, it's very easy to make mistakes when writing the `__dealloc__` and
`sparse_matrix_free` functions, leading to memory leaks. cymem prevents you from
writing these deallocators at all. Instead, you write as follows:
```python
"""Example with Cymem.
Memory allocation is hidden behind the Pool class, which remembers the
addresses it gives out. When the Pool object is garbage collected, all of
its addresses are freed.
We don't need to write MatrixArray.__dealloc__ or sparse_matrix_free,
eliminating a common class of bugs.
"""
from cymem.cymem cimport Pool
cdef struct SparseRow:
size_t length
size_t* indices
double* values
cdef struct SparseMatrix:
size_t length
SparseRow* rows
cdef class MatrixArray:
cdef size_t length
cdef SparseMatrix** matrices
cdef Pool mem
def __cinit__(self, list py_matrices):
self.mem = None
self.length = 0
self.matrices = NULL
def __init__(self, list py_matrices):
self.mem = Pool()
self.length = len(py_matrices)
self.matrices = self.mem.alloc(self.length, sizeof(SparseMatrix*))
for i, py_matrix in enumerate(py_matrices):
self.matrices[i] = sparse_matrix_init(self.mem, py_matrix)
cdef SparseMatrix* sparse_matrix_init_cymem(Pool mem, list py_matrix) except NULL:
sm = mem.alloc(1, sizeof(SparseMatrix))
sm.length = len(py_matrix)
sm.rows = mem.alloc(sm.length, sizeof(SparseRow))
cdef size_t i, j
cdef dict py_row
cdef size_t idx
cdef double value
for i, py_row in enumerate(py_matrix):
sm.rows[i].length = len(py_row)
sm.rows[i].indices = mem.alloc(sm.rows[i].length, sizeof(size_t))
sm.rows[i].values = mem.alloc(sm.rows[i].length, sizeof(double))
for j, (idx, value) in enumerate(py_row.items()):
sm.rows[i].indices[j] = idx
sm.rows[i].values[j] = value
return sm
```
All that the `Pool` class does is remember the addresses it gives out. When the
`MatrixArray` object is garbage-collected, the `Pool` object will also be garbage
collected, which triggers a call to `Pool.__dealloc__`. The `Pool` then frees all of
its addresses. This saves you from walking back over your nested data structures
to free them, eliminating a common class of errors.
## Custom Allocators
Sometimes external C libraries use private functions to allocate and free objects,
but we'd still like the laziness of the `Pool`.
```python
from cymem.cymem cimport Pool, WrapMalloc, WrapFree
cdef Pool mem = Pool(WrapMalloc(priv_malloc), WrapFree(priv_free))
```
%package help
Summary: Development documents and examples for cymem
Provides: python3-cymem-doc
%description help
# cymem: A Cython Memory Helper
cymem provides two small memory-management helpers for Cython. They make it
easy to tie memory to a Python object's life-cycle, so that the memory is freed
when the object is garbage collected.
[![Azure Pipelines](https://img.shields.io/azure-devops/build/explosion-ai/public/2/master.svg?logo=azure-pipelines&style=flat-square)](https://dev.azure.com/explosion-ai/public/_build?definitionId=2)
[![pypi Version](https://img.shields.io/pypi/v/cymem.svg?style=flat-square&logo=pypi&logoColor=white)](https://pypi.python.org/pypi/cymem)
[![conda Version](https://img.shields.io/conda/vn/conda-forge/cymem.svg?style=flat-square&logo=conda-forge&logoColor=white)](https://anaconda.org/conda-forge/cymem)
[![Python wheels](https://img.shields.io/badge/wheels-%E2%9C%93-4c1.svg?longCache=true&style=flat-square&logo=python&logoColor=white)](https://github.com/explosion/wheelwright/releases)
## Overview
The most useful is `cymem.Pool`, which acts as a thin wrapper around the calloc
function:
```python
from cymem.cymem cimport Pool
cdef Pool mem = Pool()
data1 = mem.alloc(10, sizeof(int))
data2 = mem.alloc(12, sizeof(float))
```
The `Pool` object saves the memory addresses internally, and frees them when the
object is garbage collected. Typically you'll attach the `Pool` to some cdef'd
class. This is particularly handy for deeply nested structs, which have
complicated initialization functions. Just pass the `Pool` object into the
initializer, and you don't have to worry about freeing your struct at all —
all of the calls to `Pool.alloc` will be automatically freed when the `Pool`
expires.
## Installation
Installation is via [pip](https://pypi.python.org/pypi/pip), and requires [Cython](http://cython.org). Before installing, make sure that your `pip`, `setuptools` and `wheel` are up to date.
```bash
pip install -U pip setuptools wheel
pip install cymem
```
## Example Use Case: An array of structs
Let's say we want a sequence of sparse matrices. We need fast access, and
a Python list isn't performing well enough. So, we want a C-array or C++
vector, which means we need the sparse matrix to be a C-level struct — it
can't be a Python class. We can write this easily enough in Cython:
```python
"""Example without Cymem
To use an array of structs, we must carefully walk the data structure when
we deallocate it.
"""
from libc.stdlib cimport calloc, free
cdef struct SparseRow:
size_t length
size_t* indices
double* values
cdef struct SparseMatrix:
size_t length
SparseRow* rows
cdef class MatrixArray:
cdef size_t length
cdef SparseMatrix** matrices
def __cinit__(self, list py_matrices):
self.length = 0
self.matrices = NULL
def __init__(self, list py_matrices):
self.length = len(py_matrices)
self.matrices = calloc(len(py_matrices), sizeof(SparseMatrix*))
for i, py_matrix in enumerate(py_matrices):
self.matrices[i] = sparse_matrix_init(py_matrix)
def __dealloc__(self):
for i in range(self.length):
sparse_matrix_free(self.matrices[i])
free(self.matrices)
cdef SparseMatrix* sparse_matrix_init(list py_matrix) except NULL:
sm = calloc(1, sizeof(SparseMatrix))
sm.length = len(py_matrix)
sm.rows = calloc(sm.length, sizeof(SparseRow))
cdef size_t i, j
cdef dict py_row
cdef size_t idx
cdef double value
for i, py_row in enumerate(py_matrix):
sm.rows[i].length = len(py_row)
sm.rows[i].indices = calloc(sm.rows[i].length, sizeof(size_t))
sm.rows[i].values = calloc(sm.rows[i].length, sizeof(double))
for j, (idx, value) in enumerate(py_row.items()):
sm.rows[i].indices[j] = idx
sm.rows[i].values[j] = value
return sm
cdef void* sparse_matrix_free(SparseMatrix* sm) except *:
cdef size_t i
for i in range(sm.length):
free(sm.rows[i].indices)
free(sm.rows[i].values)
free(sm.rows)
free(sm)
```
We wrap the data structure in a Python ref-counted class at as low a level as
we can, given our performance constraints. This allows us to allocate and free
the memory in the `__cinit__` and `__dealloc__` Cython special methods.
However, it's very easy to make mistakes when writing the `__dealloc__` and
`sparse_matrix_free` functions, leading to memory leaks. cymem prevents you from
writing these deallocators at all. Instead, you write as follows:
```python
"""Example with Cymem.
Memory allocation is hidden behind the Pool class, which remembers the
addresses it gives out. When the Pool object is garbage collected, all of
its addresses are freed.
We don't need to write MatrixArray.__dealloc__ or sparse_matrix_free,
eliminating a common class of bugs.
"""
from cymem.cymem cimport Pool
cdef struct SparseRow:
size_t length
size_t* indices
double* values
cdef struct SparseMatrix:
size_t length
SparseRow* rows
cdef class MatrixArray:
cdef size_t length
cdef SparseMatrix** matrices
cdef Pool mem
def __cinit__(self, list py_matrices):
self.mem = None
self.length = 0
self.matrices = NULL
def __init__(self, list py_matrices):
self.mem = Pool()
self.length = len(py_matrices)
self.matrices = self.mem.alloc(self.length, sizeof(SparseMatrix*))
for i, py_matrix in enumerate(py_matrices):
self.matrices[i] = sparse_matrix_init(self.mem, py_matrix)
cdef SparseMatrix* sparse_matrix_init_cymem(Pool mem, list py_matrix) except NULL:
sm = mem.alloc(1, sizeof(SparseMatrix))
sm.length = len(py_matrix)
sm.rows = mem.alloc(sm.length, sizeof(SparseRow))
cdef size_t i, j
cdef dict py_row
cdef size_t idx
cdef double value
for i, py_row in enumerate(py_matrix):
sm.rows[i].length = len(py_row)
sm.rows[i].indices = mem.alloc(sm.rows[i].length, sizeof(size_t))
sm.rows[i].values = mem.alloc(sm.rows[i].length, sizeof(double))
for j, (idx, value) in enumerate(py_row.items()):
sm.rows[i].indices[j] = idx
sm.rows[i].values[j] = value
return sm
```
All that the `Pool` class does is remember the addresses it gives out. When the
`MatrixArray` object is garbage-collected, the `Pool` object will also be garbage
collected, which triggers a call to `Pool.__dealloc__`. The `Pool` then frees all of
its addresses. This saves you from walking back over your nested data structures
to free them, eliminating a common class of errors.
## Custom Allocators
Sometimes external C libraries use private functions to allocate and free objects,
but we'd still like the laziness of the `Pool`.
```python
from cymem.cymem cimport Pool, WrapMalloc, WrapFree
cdef Pool mem = Pool(WrapMalloc(priv_malloc), WrapFree(priv_free))
```
%prep
%autosetup -n cymem-2.0.7
%build
%py3_build
%install
%py3_install
install -d -m755 %{buildroot}/%{_pkgdocdir}
if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi
if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi
if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi
if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi
pushd %{buildroot}
if [ -d usr/lib ]; then
find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst
fi
if [ -d usr/lib64 ]; then
find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst
fi
if [ -d usr/bin ]; then
find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst
fi
if [ -d usr/sbin ]; then
find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst
fi
touch doclist.lst
if [ -d usr/share/man ]; then
find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst
fi
popd
mv %{buildroot}/filelist.lst .
mv %{buildroot}/doclist.lst .
%files -n python3-cymem -f filelist.lst
%dir %{python3_sitearch}/*
%files help -f doclist.lst
%{_docdir}/*
%changelog
* Mon Apr 10 2023 Python_Bot - 2.0.7-1
- Package Spec generated