Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python 3.12 changes #44

Merged
merged 16 commits into from
Jul 21, 2024
1 change: 0 additions & 1 deletion .github/workflows/sphinx.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
name: Sphinx
on:
- push
- pull_request

jobs:
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/upload-pypi-source.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
name: Build

on: [push, pull_request]
on: [pull_request]

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", pypy3.9]
python-version: ["3.11", "3.12", "pypy3.9", "pypy3.10"]
dholth marked this conversation as resolved.
Show resolved Hide resolved

steps:
- uses: actions/checkout@v3
Expand All @@ -20,7 +20,7 @@ jobs:
run: python -c "import sys; print(sys.version)"
- name: Build
run: |
python -m pip install scons pytoml packaging
python -m pip install scons tomli packaging
scons -c
scons
python -m pip install dist/enscons*.whl
Expand Down
6 changes: 6 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
0.30.0
------
- Support Python 3.12 with removed distutils, imp.
- Use setuptools for enscons.cpyext, only required for enscons projects with extensions.
- Use tomllib (Python 3.11+) or tomli.

0.28.0
------
- Update editables for approved PEP 660
Expand Down
5 changes: 2 additions & 3 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,10 @@
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.

import pytoml as toml
import enscons.toml as toml
import enscons
import sys

metadata = toml.load(open("pyproject.toml"))["project"]
metadata = toml.load(open("pyproject.toml", "rb"))["project"]

full_tag = "py2.py3-none-any"

Expand Down
21 changes: 10 additions & 11 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

project = 'enscons'
copyright = '2023, Daniel Holth & enscons developers'
author = 'Daniel Holth & enscons developers'
release = '0.28.0'
project = "enscons"
copyright = "2023, Daniel Holth & enscons developers"
author = "Daniel Holth & enscons developers"
release = "0.30.0"

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
Expand All @@ -18,17 +18,16 @@
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'myst_parser',
"sphinx.ext.autodoc",
"myst_parser",
]

templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']

templates_path = ["_templates"]
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]


# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

html_theme = 'furo'
html_static_path = ['_static']
html_theme = "furo"
html_static_path = ["_static"]
8 changes: 4 additions & 4 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ builder, a `WhlFile` builder, and an `SDist` builder.
Here's a simple and complete example. The following sections will go over each part in more detail.

```python
import pytoml as toml
import tomllib
import enscons

metadata = toml.load(open("pyproject.toml"))["project"]
metadata = tomllib.load(open("pyproject.toml", "rb"))["project"]
tag = "py3-none-any"

env = Environment(
Expand All @@ -110,7 +110,7 @@ by the SCons runtime.
The SConstruct `Environment` object should be created as shown:

```python
metadata = toml.load(open("pyproject.toml"))["project"]
metadata = tomllib.load(open("pyproject.toml", "rb"))["project"]
tag = "py3-none-any"

env = Environment(
Expand Down Expand Up @@ -234,7 +234,7 @@ These variables are settable using kwargs to the `Environment()` constructor.

.. code-block:: python

metadata = toml.load(open("pyproject.toml"))["project"]
metadata = toml.load(open("pyproject.toml", "rb"))["project"]

This variable is required.

Expand Down
4 changes: 2 additions & 2 deletions enscons/SConstruct.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
# (filled by enscons.setup2toml)

import enscons
import pytoml as toml
import enscons.toml as toml

metadata = dict(toml.load(open("pyproject.toml")))["project"]
metadata = dict(toml.load(open("pyproject.toml", "rb")))["project"]

# set to True if package is not pure Python
HAS_NATIVE_CODE = False
Expand Down
15 changes: 5 additions & 10 deletions enscons/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,9 @@

from SCons.Script import Copy, Action, FindInstalledFiles, GetOption, AddOption

from distutils import sysconfig
from collections import defaultdict

from .util import safe_name, to_filename, generate_requirements

import codecs
import distutils.ccompiler, distutils.sysconfig, distutils.unixccompiler
import os.path
import SCons.Node.FS

Expand All @@ -82,7 +78,7 @@ def get_binary_tag():
"""
from packaging import tags

return str(next(tag for tag in tags.sys_tags() if not "manylinux" in tag.platform))
return str(next(tag for tag in tags.sys_tags() if "manylinux" not in tag.platform))


def get_universal_tag():
Expand Down Expand Up @@ -187,7 +183,7 @@ def egg_info_builder(target, source, env):
"""
Minimum egg_info. To be used only by pip to get dependencies.
"""
metadata = env["PACKAGE_METADATA"]
env["PACKAGE_METADATA"]
dholth marked this conversation as resolved.
Show resolved Hide resolved
for dnode in env.arg2nodes(target):
if dnode.name == "PKG-INFO":
with open(dnode.get_path(), "w") as f:
Expand Down Expand Up @@ -249,7 +245,7 @@ def metadata_source(env):
# Maybe the two should be unified.
if "license" in metadata:
if not _is_string(metadata["license"]):
if not ("text" in metadata["license"]):
if "text" not in metadata["license"]:
source.append(metadata["license"]["file"])
if "readme" in metadata:
if _is_string(metadata["readme"]):
Expand Down Expand Up @@ -386,7 +382,6 @@ def add_editable(target, source, env):
archive = zipfile.ZipFile(
target[0].get_path(), "a", compression=zipfile.ZIP_DEFLATED
)
lines = []
for f, data in project.files():
archive.writestr(zipfile.ZipInfo(f, time.gmtime(SOURCE_EPOCH_ZIP)[:6]), data)
archive.close()
Expand Down Expand Up @@ -497,7 +492,7 @@ def init_wheel(env):
# editable may need an extra dependency, so it gets its own dist-info directory.
env.Command(editable_dist_info, env["DIST_INFO_PATH"], Copy("$TARGET", "$SOURCE"))

metadata2 = env.Command(
env.Command(
editable_dist_info.File("METADATA"), metadata_source(env), metadata_builder
)

Expand Down Expand Up @@ -593,7 +588,7 @@ def SDist(env, target=None, source=None):
env.Clean(egg_info, env["EGG_INFO_PATH"])
env.Alias("egg_info", egg_info)

pkg_info = env.Command("PKG-INFO", metadata_source(env), metadata_builder)
env.Command("PKG-INFO", metadata_source(env), metadata_builder)

# also the root directory name inside the archive
target_prefix = "-".join((env["PACKAGE_NAME"], env["PACKAGE_VERSION"]))
Expand Down
5 changes: 3 additions & 2 deletions enscons/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
def _run(alias):
try:
SCons.Script.Main.main()
except SystemExit:
pass
except SystemExit as e:
if e.code != 0:
raise
# extreme non-api:
lookup = SCons.Node.arg2nodes_lookups[0](alias).sources[0]
return os.path.basename(str(lookup))
Expand Down
4 changes: 2 additions & 2 deletions enscons/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
import pprint
import os.path
import click
import pytoml as toml
import tomllib as toml


class Backend(object):
def __init__(self):
self.metadata = dict(toml.load(open("pyproject.toml")))
self.metadata = dict(toml.load(open("pyproject.toml", "rb")))
build_backend = self.metadata["build-system"]["build-backend"]
module, _, obj = build_backend.partition(":")
__import__(module)
Expand Down
27 changes: 13 additions & 14 deletions enscons/cpyext.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@

from __future__ import print_function

import distutils.sysconfig, sysconfig, os, os.path
import sysconfig
import os
import os.path

from distutils.core import Distribution
from distutils.extension import Extension
from distutils.command.build_ext import build_ext
from setuptools import Distribution
from setuptools.extension import Extension
from setuptools.command.build_ext import build_ext

import imp
import importlib
import importlib.machinery


# not used when generate is passed directly to Environment
def exists(env):
Expand All @@ -28,8 +31,6 @@ def extension_filename(modname, abi3=False):
If abi3=True and supported by the interpreter, return e.g.
"a/b/c.abi3.so".
"""
from distutils.sysconfig import get_config_var

# we could probably just split modname by '.' instead of using ext here:
ext = get_build_ext()
fullname = ext.get_ext_fullname(modname)
Expand All @@ -42,10 +43,7 @@ def extension_filename(modname, abi3=False):
suffix = suffixes[0] if suffixes else None
except AttributeError:
pass
if not suffix:
suffix = get_config_var("EXT_SUFFIX")
if not suffix:
suffix = get_config_var("SO") # py2
suffix = sysconfig.get_config_var("EXT_SUFFIX")

if abi3:
suffix = get_abi3_suffix() or suffix
Expand All @@ -55,6 +53,7 @@ def extension_filename(modname, abi3=False):

class no_build_ext(build_ext):
output = [] # for testing

# Are you kidding me? We have to run build_ext() to finish configuring the compiler.
def build_extension(self, ext):
def noop_spawn(*args):
Expand Down Expand Up @@ -88,7 +87,7 @@ def get_build_ext(name="zoot"):
# from setuptools
def get_abi3_suffix():
"""Return the file extension for an abi3-compliant Extension()"""
for suffix, _, _ in (s for s in imp.get_suffixes() if s[2] == imp.C_EXTENSION):
for suffix in importlib.machinery.EXTENSION_SUFFIXES:
if ".abi3" in suffix: # Unix
return suffix
elif suffix == ".pyd": # Windows
Expand All @@ -102,8 +101,8 @@ def generate(env):
# Actually this has side effects adding redundant arguments to ext's compiler.
# Could copy the compiler from ext before run() is called.
if False:
compiler = distutils.ccompiler.new_compiler()
distutils.sysconfig.customize_compiler(compiler)
compiler = setuptools.ccompiler.new_compiler()
setuptools.sysconfig.customize_compiler(compiler)

ext = get_build_ext()

Expand Down
6 changes: 3 additions & 3 deletions enscons/pytar.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ def tar(target, source, env):

def _filter(info):
"""Return potentially anonymize tarinfo"""
if taruid != None:
if taruid is not None:
info.uid = taruid
info.uname = ""
if targid != None:
if targid is not None:
info.gid = targid
info.gname = ""
if tarmtime != None:
if tarmtime is not None:
info.mtime = tarmtime
return info

Expand Down
6 changes: 5 additions & 1 deletion enscons/setup.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
"""
enscons' implementation of setup.py, to be called from a shim setup.py for
compatibility with traditional style packaging & tools.

Now that pyproject.toml is widely supported, this should not be needed.
"""

import sys, pkg_resources, argparse
import sys
import pkg_resources
import argparse


def develop(path):
Expand Down
22 changes: 15 additions & 7 deletions enscons/setup2toml.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@

import runpy
from collections import OrderedDict
import setuptools, distutils.core
import sys, os, codecs, errno
import pytoml
import setuptools
try:
import distutils.core as distutils_core
except ImportError:
distutils_core = None
import sys
import os
import codecs
import errno
import tomli_w

import pkgutil

Expand Down Expand Up @@ -90,7 +97,8 @@ def setup_(**kw):
setup_.arguments = kw

setuptools.setup = setup_
distutils.core.setup = setup_
if distutils_core:
distutils_core.setup = setup_

sys.path[0:0] = "."

Expand Down Expand Up @@ -138,14 +146,14 @@ def setup_(**kw):
if "long_description" in ordered_arguments:
sys.stderr.write("Consider replacing long_description with description_file\n")

pyproject = pytoml.dumps(
OrderedDict(
pyproject = tomli_w.dumps(
dict(
[
["project", ordered_arguments],
[
"build-system",
{
"requires": ["pytoml>=0.1", "enscons"],
"requires": ["enscons"],
"build-backend": "enscons.api",
},
],
Expand Down
8 changes: 8 additions & 0 deletions enscons/toml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""
Import available toml.load
"""
try:
# Python 3.11+
from tomllib import load
except ImportError:
from tomli import load
Loading
Loading