formal support for 3.12, initial support for 3.13 (#630)

* formal support for 3.12, initial support for 3.13

* use NamedTemporaryFile('w').file in 3.13
diff --git a/.travis.yml b/.travis.yml
index adc67a0..96c6134 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -17,21 +17,24 @@
         - python: '3.11'
           env:
 
-        - python: '3.12-dev'
+        - python: '3.12'
+          env:
+
+        - python: '3.13-dev'
           env:
 
         - python: 'pypy3.8-7.3.9' # at 7.3.11
           env:
 
-        - python: 'pypy3.9-7.3.9' # at 7.3.12
+        - python: 'pypy3.9-7.3.9' # at 7.3.13
           env:
 
-        - python: 'pypy3.10-7.3.12'
+        - python: 'pypy3.10-7.3.13'
           env:
 
     allow_failures:
-        - python: '3.12-dev'
-        - python: 'pypy3.10-7.3.12' # CI missing
+        - python: '3.13-dev'
+        - python: 'pypy3.10-7.3.13' # CI missing
     fast_finish: true
 
 cache:
diff --git a/dill/_dill.py b/dill/_dill.py
index 3dcff76..d7afd5f 100644
--- a/dill/_dill.py
+++ b/dill/_dill.py
@@ -2018,9 +2018,11 @@
     _PyCapsule_SetName.argtypes = (ctypes.py_object, ctypes.c_char_p)
     _PyCapsule_SetPointer = ctypes.pythonapi.PyCapsule_SetPointer
     _PyCapsule_SetPointer.argtypes = (ctypes.py_object, ctypes.c_void_p)
+    #from _socket import CAPI as _testcapsule
+    _testcapsule_name = b'dill._dill._testcapsule'
     _testcapsule = _PyCapsule_New(
         ctypes.cast(_PyCapsule_New, ctypes.c_void_p),
-        ctypes.create_string_buffer(b'dill._dill._testcapsule'),
+        ctypes.c_char_p(_testcapsule_name),
         None
     )
     PyCapsuleType = type(_testcapsule)
diff --git a/dill/_objects.py b/dill/_objects.py
index dc2c5c3..414c62d 100644
--- a/dill/_objects.py
+++ b/dill/_objects.py
@@ -39,7 +39,6 @@
 import gzip
 import zipfile
 import tarfile
-import xdrlib
 import csv
 import hashlib
 import hmac
@@ -110,7 +109,10 @@
         pass
     _Struct._fields_ = [("_field", ctypes.c_int),("next", ctypes.POINTER(_Struct))]
 _filedescrip, _tempfile = tempfile.mkstemp('r') # deleted in cleanup
-_tmpf = tempfile.TemporaryFile('w')
+if sys.hexversion < 0x30d00a1:
+    _tmpf = tempfile.TemporaryFile('w') # emits OSError 9 in python 3.13
+else:
+    _tmpf = tempfile.NamedTemporaryFile('w').file # for > python 3.9
 
 # objects used by dill for type declaration
 registered = d = {}
@@ -313,7 +315,9 @@
 a['TarFileType'] = tarfile.open(fileobj=_fileW,mode='w')
 # file formats (CH 13)
 x['DialectType'] = csv.get_dialect('excel')
-a['PackerType'] = xdrlib.Packer()
+if sys.hexversion < 0x30d00a1:
+    import xdrlib
+    a['PackerType'] = xdrlib.Packer()
 # optional operating system services (CH 16)
 a['LockType'] = threading.Lock()
 a['RLockType'] = threading.RLock()
diff --git a/dill/detect.py b/dill/detect.py
index a957634..4f02a7b 100644
--- a/dill/detect.py
+++ b/dill/detect.py
@@ -150,7 +150,7 @@
         if '_GLOBAL' in line:
             name = line.split('(')[-1].split(')')[0]
             if CAN_NULL:
-                names.add(name.replace('NULL + ', ''))
+                names.add(name.replace('NULL + ', '').replace(' + NULL', ''))
             else:
                 names.add(name)
     for co in getattr(func, 'co_consts', tuple()):
diff --git a/dill/tests/test_objects.py b/dill/tests/test_objects.py
index 4719a0d..0735a1c 100644
--- a/dill/tests/test_objects.py
+++ b/dill/tests/test_objects.py
@@ -35,7 +35,7 @@
 special['UnboundMethodType'] = _class._method
 objects.update(special)
 
-def pickles(name, exact=False):
+def pickles(name, exact=False, verbose=True):
     """quick check if object pickles with dill"""
     obj = objects[name]
     try:
@@ -45,19 +45,19 @@
                 assert pik == obj
             except AssertionError:
                 assert type(obj) == type(pik)
-                print ("weak: %s %s" % (name, type(obj)))
+                if verbose: print ("weak: %s %s" % (name, type(obj)))
         else:
             assert type(obj) == type(pik)
     except Exception:
-        print ("fails: %s %s" % (name, type(obj)))
+        if verbose: print ("fails: %s %s" % (name, type(obj)))
 
 
-def test_objects():
+def test_objects(verbose=True):
     for member in objects.keys():
-       #pickles(member, exact=True)
-        pickles(member, exact=False)
+       #pickles(member, exact=True, verbose=verbose)
+        pickles(member, exact=False, verbose=verbose)
 
 if __name__ == '__main__':
     import warnings
     warnings.simplefilter('ignore')
-    test_objects()
+    test_objects(verbose=False)
diff --git a/setup.py b/setup.py
index 22b86db..bde82a4 100644
--- a/setup.py
+++ b/setup.py
@@ -66,6 +66,7 @@
         'Programming Language :: Python :: 3.9',
         'Programming Language :: Python :: 3.10',
         'Programming Language :: Python :: 3.11',
+        'Programming Language :: Python :: 3.12',
         'Programming Language :: Python :: Implementation :: CPython',
         'Programming Language :: Python :: Implementation :: PyPy',
         'Topic :: Scientific/Engineering',
diff --git a/tox.ini b/tox.ini
index 3aa21d7..08a7120 100644
--- a/tox.ini
+++ b/tox.ini
@@ -7,6 +7,7 @@
     py310
     py311
     py312
+    py313
     pypy38
     pypy39
     pypy310