-import gc
import pytest
import string
from random import randrange, choice
from psycopg.adapt import PyFormat
from psycopg.types.numeric import Int4
-from ..utils import eur, gc_collect
+from ..utils import eur, gc_collect, gc_count
from ..test_copy import sample_text, sample_binary # noqa
from ..test_copy import ensure_table, sample_records
from ..test_copy import sample_tabledef as sample_tabledef_pg
for i in range(3):
work()
gc_collect()
- n.append(len(gc.get_objects()))
+ n.append(gc_count())
assert n[0] == n[1] == n[2], f"objects leaked: {n[1] - n[0]}, {n[2] - n[1]}"
-import gc
import pytest
import string
from random import randrange, choice
from psycopg.adapt import PyFormat
from psycopg.types.numeric import Int4
-from ..utils import eur, gc_collect
+from ..utils import eur, gc_collect, gc_count
from ..test_copy import sample_text, sample_binary # noqa
from ..test_copy import sample_records
from ..test_copy_async import ensure_table
for i in range(3):
await work()
gc_collect()
- n.append(len(gc.get_objects()))
+ n.append(gc_count())
assert n[0] == n[1] == n[2], f"objects leaked: {n[1] - n[0]}, {n[2] - n[1]}"
-import gc
import pickle
import weakref
import datetime as dt
from psycopg.adapt import PyFormat
from psycopg.postgres import types as builtins
-from .utils import gc_collect
+from .utils import gc_collect, gc_count
from .test_cursor import my_row_factory
from .fix_crdb import is_crdb, crdb_encoding, crdb_time_precision
for i in range(3):
work()
gc_collect()
- n.append(len(gc.get_objects()))
+ n.append(gc_count())
assert n[0] == n[1] == n[2], f"objects leaked: {n[1] - n[0]}, {n[2] - n[1]}"
-import gc
import pytest
import weakref
import datetime as dt
from psycopg import sql, rows
from psycopg.adapt import PyFormat
-from .utils import alist, gc_collect
+from .utils import alist, gc_collect, gc_count
from .test_cursor import my_row_factory
from .test_cursor import execmany, _execmany # noqa: F401
from .fix_crdb import crdb_encoding
for i in range(3):
await work()
gc_collect()
- n.append(len(gc.get_objects()))
+ n.append(gc_count())
assert n[0] == n[1] == n[2], f"objects leaked: {n[1] - n[0]}, {n[2] - n[1]}"
-import gc
import string
import struct
import hashlib
from psycopg.types.hstore import register_hstore
from psycopg.types.numeric import Int4
-from .utils import eur, gc_collect
+from .utils import eur, gc_collect, gc_count
pytestmark = pytest.mark.crdb_skip("copy")
for i in range(3):
work()
gc_collect()
- n.append(len(gc.get_objects()))
+ n.append(gc_count())
assert n[0] == n[1] == n[2], f"objects leaked: {n[1] - n[0]}, {n[2] - n[1]}"
for i in range(3):
work()
gc_collect()
- n.append(len(gc.get_objects()))
+ n.append(gc_count())
assert n[0] == n[1] == n[2], f"objects leaked: {n[1] - n[0]}, {n[2] - n[1]}"
-import gc
import string
import hashlib
from io import BytesIO, StringIO
from psycopg.types.hstore import register_hstore
from psycopg.types.numeric import Int4
-from .utils import alist, eur, gc_collect
+from .utils import alist, eur, gc_collect, gc_count
from .test_copy import sample_text, sample_binary, sample_binary_rows # noqa
from .test_copy import sample_values, sample_records, sample_tabledef
from .test_copy import py_to_raw, special_chars
for i in range(3):
await work()
gc_collect()
- n.append(len(gc.get_objects()))
+ n.append(gc_count())
assert n[0] == n[1] == n[2], f"objects leaked: {n[1] - n[0]}, {n[2] - n[1]}"
for i in range(3):
await work()
gc_collect()
- n.append(len(gc.get_objects()))
+ n.append(gc_count())
assert n[0] == n[1] == n[2], f"objects leaked: {n[1] - n[0]}, {n[2] - n[1]}"
-import gc
import pickle
import weakref
import datetime as dt
from psycopg.postgres import types as builtins
from psycopg.rows import RowMaker
-from .utils import gc_collect
+from .utils import gc_collect, gc_count
from .fix_crdb import is_crdb, crdb_encoding, crdb_time_precision
for i in range(3):
work()
gc_collect()
- n.append(len(gc.get_objects()))
+ n.append(gc_count())
assert n[0] == n[1] == n[2], f"objects leaked: {n[1] - n[0]}, {n[2] - n[1]}"
-import gc
import pytest
import weakref
import datetime as dt
from psycopg import pq, sql, rows
from psycopg.adapt import PyFormat
-from .utils import gc_collect
+from .utils import gc_collect, gc_count
from .test_cursor import my_row_factory
from .test_cursor import execmany, _execmany # noqa: F401
from .fix_crdb import crdb_encoding
for i in range(3):
await work()
gc_collect()
- n.append(len(gc.get_objects()))
+ n.append(gc_count())
assert n[0] == n[1] == n[2], f"objects leaked: {n[1] - n[0]}, {n[2] - n[1]}"
import gc
import re
+import sys
import operator
from typing import Callable, Optional, Tuple
gc.collect()
+NO_COUNT_TYPES: Tuple[type, ...] = ()
+
+if sys.version_info[:2] == (3, 10):
+ # On my laptop there are occasional creations of a single one of these objects
+ # with empty content, which might be some Decimal caching.
+ # Keeping the guard as strict as possible, to be extended if other types
+ # or versions are necessary.
+ try:
+ from _contextvars import Context # type: ignore
+ except ImportError:
+ pass
+ else:
+ NO_COUNT_TYPES += (Context,)
+
+
+def gc_count() -> int:
+ """
+ len(gc.get_objects()), with subtleties.
+ """
+ if not NO_COUNT_TYPES:
+ return len(gc.get_objects())
+
+ # Note: not using a list comprehension because it pollutes the objects list.
+ rv = 0
+ for obj in gc.get_objects():
+ if isinstance(obj, NO_COUNT_TYPES):
+ continue
+ rv += 1
+
+ return rv
+
+
async def alist(it):
return [i async for i in it]