From ca1adbc94c57d3ceb04ea9e648e28f1fbaa56dc6 Mon Sep 17 00:00:00 2001
From: MilesCranmer <miles.cranmer@gmail.com>
Date: Mon, 30 Oct 2023 23:41:51 +0000
Subject: [PATCH 1/7] Fix importlib deprecated API

---
 src/julia/core.py | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/julia/core.py b/src/julia/core.py
index 183298c4..d387d338 100644
--- a/src/julia/core.py
+++ b/src/julia/core.py
@@ -24,6 +24,8 @@
 import textwrap
 import warnings
 from ctypes import c_char_p, c_void_p
+from importlib.abc import Loader, MetaPathFinder
+from importlib.machinery import ModuleSpec
 from logging import getLogger  # see `.logger`
 from types import ModuleType  # this is python 3.3 specific
 
@@ -220,27 +222,25 @@ def __setattr__(self, name, value):
 
 
 # add custom import behavior for the julia "module"
-class JuliaImporter(object):
+class JuliaImporter(MetaPathFinder):
 
-    # find_module was deprecated in v3.4
-    def find_module(self, fullname, path=None):
+    def find_spec(self, fullname, path=None, target=None):
         if fullname.startswith("julia."):
             filename = fullname.split(".", 2)[1]
             filepath = os.path.join(os.path.dirname(__file__), filename)
             if os.path.isfile(filepath + ".py") or os.path.isdir(filepath):
                 return
-            return JuliaModuleLoader()
+            return ModuleSpec(fullname, JuliaModuleLoader())
 
 
-class JuliaModuleLoader(object):
-
+class JuliaModuleLoader(Loader):
     @property
     def julia(self):
         self.__class__.julia = julia = Julia()
         return julia
 
-    # load module was deprecated in v3.4
-    def load_module(self, fullname):
+    def exec_module(self, module):
+        fullname = module.__name__
         juliapath = remove_prefix(fullname, "julia.")
         if juliapath == 'Main':
             return sys.modules.setdefault(fullname,

From 930c22a8fa3177fd185c72e138063d72b4516c1e Mon Sep 17 00:00:00 2001
From: MilesCranmer <miles.cranmer@gmail.com>
Date: Mon, 30 Oct 2023 23:43:23 +0000
Subject: [PATCH 2/7] Test Python 3.12

---
 .github/workflows/main.yml | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 3f9f8e91..fa9abf90 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -20,10 +20,9 @@ jobs:
         architecture: [x64, x86]
         python-version:
           - '3.9'
-          - '3.10'
+          - '3.12'
         julia-version:
           - '1.4'
-          - '1.6'
           - '1.7'
           - '1.8'
         exclude:

From 546d2ee89f4a5f84d48d91b28c2d66a3e8843e08 Mon Sep 17 00:00:00 2001
From: MilesCranmer <miles.cranmer@gmail.com>
Date: Mon, 30 Oct 2023 23:43:29 +0000
Subject: [PATCH 3/7] Test Julia 1.9

---
 .github/workflows/main.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index fa9abf90..918c457e 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -25,6 +25,7 @@ jobs:
           - '1.4'
           - '1.7'
           - '1.8'
+          - '1.9'
         exclude:
           - os: ubuntu-latest
             architecture: x86

From 02a626bfc2ae29b5819fb0c9e4b0f31b87cd5650 Mon Sep 17 00:00:00 2001
From: MilesCranmer <miles.cranmer@gmail.com>
Date: Sun, 5 Nov 2023 21:14:16 +0000
Subject: [PATCH 4/7] Fix semantics of exec_module vs create_module

---
 src/julia/core.py | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/julia/core.py b/src/julia/core.py
index d387d338..a5cd3aea 100644
--- a/src/julia/core.py
+++ b/src/julia/core.py
@@ -230,7 +230,7 @@ def find_spec(self, fullname, path=None, target=None):
             filepath = os.path.join(os.path.dirname(__file__), filename)
             if os.path.isfile(filepath + ".py") or os.path.isdir(filepath):
                 return
-            return ModuleSpec(fullname, JuliaModuleLoader())
+            return ModuleSpec(fullname, JuliaModuleLoader(), origin=filepath)
 
 
 class JuliaModuleLoader(Loader):
@@ -240,7 +240,10 @@ def julia(self):
         return julia
 
     def exec_module(self, module):
-        fullname = module.__name__
+        pass
+
+    def create_module(self, spec):
+        fullname = spec.name
         juliapath = remove_prefix(fullname, "julia.")
         if juliapath == 'Main':
             return sys.modules.setdefault(fullname,

From 6feab5ae3cd903168e3bbfda0916b4c557633f63 Mon Sep 17 00:00:00 2001
From: MilesCranmer <miles.cranmer@gmail.com>
Date: Sun, 5 Nov 2023 21:41:31 +0000
Subject: [PATCH 5/7] Ensure we can find spec from JuliaModule

---
 src/julia/core.py | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/src/julia/core.py b/src/julia/core.py
index a5cd3aea..5120b28f 100644
--- a/src/julia/core.py
+++ b/src/julia/core.py
@@ -191,7 +191,7 @@ def __try_getattr(self, name):
         if self._julia.isamodule(jl_fullname):
             realname = self._julia.fullname(self._julia.eval(jl_fullname))
             if self._julia.isdefined(realname):
-                return self.__loader__.load_module("julia." + realname)
+                return self.__loader__.create_module(_find_spec_from_fullname("julia." + realname))
             # Otherwise, it may be, e.g., "Main.anonymous", created by
             # Module().
 
@@ -225,14 +225,17 @@ def __setattr__(self, name, value):
 class JuliaImporter(MetaPathFinder):
 
     def find_spec(self, fullname, path=None, target=None):
-        if fullname.startswith("julia."):
-            filename = fullname.split(".", 2)[1]
-            filepath = os.path.join(os.path.dirname(__file__), filename)
-            if os.path.isfile(filepath + ".py") or os.path.isdir(filepath):
-                return
-            return ModuleSpec(fullname, JuliaModuleLoader(), origin=filepath)
+        return _find_spec_from_fullname(fullname)
 
 
+def _find_spec_from_fullname(fullname):
+    if fullname.startswith("julia."):
+        filename = fullname.split(".", 2)[1]
+        filepath = os.path.join(os.path.dirname(__file__), filename)
+        if os.path.isfile(filepath + ".py") or os.path.isdir(filepath):
+            return
+        return ModuleSpec(fullname, JuliaModuleLoader(), origin=filepath)
+
 class JuliaModuleLoader(Loader):
     @property
     def julia(self):

From 06cc12e2d5539016027f0b6bfcd4bf68dbdeff7e Mon Sep 17 00:00:00 2001
From: MilesCranmer <miles.cranmer@gmail.com>
Date: Fri, 15 Dec 2023 00:03:19 -0600
Subject: [PATCH 6/7] Bump version with python 3.12 compat

---
 src/julia/release.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/julia/release.py b/src/julia/release.py
index b91b9912..85a16f2c 100644
--- a/src/julia/release.py
+++ b/src/julia/release.py
@@ -1,5 +1,5 @@
 # This file is executed via setup.py and imported via __init__.py
 
-__version__ = "0.6.1"
+__version__ = "0.6.2"
 # For Python versioning scheme, see:
 # https://www.python.org/dev/peps/pep-0440/#version-scheme

From 13abc676cb4075496065adc111dc6ebecceaf8d5 Mon Sep 17 00:00:00 2001
From: MilesCranmer <miles.cranmer@gmail.com>
Date: Sat, 16 Dec 2023 08:32:27 -0600
Subject: [PATCH 7/7] Declare compat for 3.11 and 3.12

---
 setup.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/setup.py b/setup.py
index 6a1870e7..3208dae2 100644
--- a/setup.py
+++ b/setup.py
@@ -67,6 +67,8 @@ def pyload(path):
         'Programming Language :: Python :: 3.8',
         'Programming Language :: Python :: 3.9',
         'Programming Language :: Python :: 3.10',
+        'Programming Language :: Python :: 3.11',
+        'Programming Language :: Python :: 3.12',
       ],
       url='http://julialang.org',
       project_urls={