Skip to content
This repository was archived by the owner on Jan 20, 2025. It is now read-only.

Fix clean up of downloaded modules when using go.mod #50

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 24 additions & 10 deletions setuptools_golang.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import argparse
import contextlib
import copy
import errno
import os
import shlex
import shutil
Expand All @@ -10,6 +11,8 @@
import tempfile
from distutils.ccompiler import CCompiler
from distutils.dist import Distribution
from types import TracebackType
from typing import Any
from typing import Callable
from typing import Dict
from typing import Generator
Expand All @@ -22,22 +25,33 @@
from setuptools.command.build_ext import build_ext as _build_ext


def rmtree(path: str) -> None:
"""Newer golang uses readonly dirs & files for module cache."""
def handle_remove_readonly(
func: Callable[..., Any],
path: str,
exc: Tuple[Type[OSError], OSError, TracebackType],
) -> None:
excvalue = exc[1]
if (
func in (os.rmdir, os.remove, os.unlink) and
excvalue.errno == errno.EACCES
):
for p in (path, os.path.dirname(path)):
os.chmod(p, os.stat(p).st_mode | stat.S_IWUSR)
func(path)
else:
raise
shutil.rmtree(path, ignore_errors=False, onerror=handle_remove_readonly)


@contextlib.contextmanager
def _tmpdir() -> Generator[str, None, None]:
tempdir = tempfile.mkdtemp()
try:
yield tempdir
finally:
def err(
action: Callable[[str], None],
name: str,
exc: Exception,
) -> None: # pragma: no cover (windows)
"""windows: can't remove readonly files, make them writeable!"""
os.chmod(name, stat.S_IWRITE)
action(name)

shutil.rmtree(tempdir, onerror=err)
rmtree(tempdir)


def _get_cflags(
Expand Down
5 changes: 5 additions & 0 deletions testing/gomodules/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/asottile/setuptools-golang/testing/gomodules

go 1.14

require github.com/golang/example v0.0.0-20170904185048-46695d81d1fa
2 changes: 2 additions & 0 deletions testing/gomodules/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/golang/example v0.0.0-20170904185048-46695d81d1fa h1:iqCQC2Z53KkwGgTN9szyL4q0OQHmuNjeoNnMT6lk66k=
github.com/golang/example v0.0.0-20170904185048-46695d81d1fa/go.mod h1:tO/5UvQ/uKigUjQBPqzstj6uxd3fUIjddi19DxGJeWg=
19 changes: 19 additions & 0 deletions testing/gomodules/reversemsg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

// #include <Python.h>
import "C"

import (
"fmt"

"github.com/golang/example/stringutil"
)

//export reversemsg
func reversemsg() *C.PyObject {
fmt.Print(stringutil.Reverse("elpmaxe tset"))

return C.Py_None
}

func main() {}
29 changes: 29 additions & 0 deletions testing/gomodules/reversemsg_support.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package main

// #include <Python.h>
//
// PyObject* reversemsg();
//
// static struct PyMethodDef methods[] = {
// {"reversemsg", (PyCFunction)reversemsg, METH_NOARGS},
// {NULL, NULL}
// };
//
// #if PY_MAJOR_VERSION >= 3
// static struct PyModuleDef module = {
// PyModuleDef_HEAD_INIT,
// "gomodules",
// NULL,
// -1,
// methods
// };
//
// PyMODINIT_FUNC PyInit_gomodules(void) {
// return PyModule_Create(&module);
// }
// #else
// PyMODINIT_FUNC initgomodules(void) {
// Py_InitModule3("gomodules", methods, NULL);
// }
// #endif
import "C"
15 changes: 15 additions & 0 deletions testing/gomodules/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from setuptools import Extension
from setuptools import setup


setup(
name='gomod',
ext_modules=[Extension('gomodules', ['reversemsg.go'])],
build_golang={
'root': 'github.com/asottile/setuptools-golang/testing/gomodules',
},
# Would do this, but we're testing *our* implementation and this would
# install from pypi. We can rely on setuptools-golang being already
# installed under test.
# setup_requires=['setuptools-golang'],
)
9 changes: 9 additions & 0 deletions tests/setuptools_golang_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,15 @@ def test_integration_imports_gh(venv):
assert out == '\x1b[0;31mohai\x1b[0m\n'


GOMOD = 'import gomodules; gomodules.reversemsg()'


def test_integration_gomodules(venv):
run(venv.pip, 'install', os.path.join('testing', 'gomodules'))
out = run_output(venv.python, '-c', GOMOD)
assert out == 'test example'


def test_integration_notfound(venv):
ret = run(
venv.pip, 'install', os.path.join('testing', 'notfound'),
Expand Down