[Jython-checkins] jython (merge default -> default): Merge Gradle build script addition to trunk.

jeff.allen jython-checkins at python.org
Wed Jul 11 14:53:19 EDT 2018


https://hg.python.org/jython/rev/ebd8868b8323
changeset:   8171:ebd8868b8323
parent:      8169:e546ad3d85bd
parent:      8170:921c66481876
user:        Jeff Allen <ja.py at farowl.co.uk>
date:        Wed Jul 11 19:46:40 2018 +0100
summary:
  Merge Gradle build script addition to trunk.

files:
  .gitignore                                      |    6 +
  .hgignore                                       |    6 +
  build.gradle                                    |  755 ++++++++++
  gradle/wrapper/gradle-wrapper.jar               |  Bin 
  gradle/wrapper/gradle-wrapper.properties        |    5 +
  gradlew                                         |  172 ++
  gradlew.bat                                     |   84 +
  settings.gradle                                 |    5 +
  tests/java/org/python/core/BaseBytesTest.java   |   12 +-
  tests/java/org/python/core/PyBufferTest.java    |    2 +-
  tests/java/org/python/core/PyByteArrayTest.java |   27 +-
  11 files changed, 1057 insertions(+), 17 deletions(-)


diff --git a/.gitignore b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,9 @@
 *.swp
 \#*
 *~
+
+.gradle
+
 # IntelliJ files
 *.eml
 *.ipr
@@ -32,8 +35,11 @@
 __pycache__
 ant.properties
 bin
+
 build
+build2
 cachedir
 dist
 target
+
 profile.txt
diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -8,6 +8,9 @@
 *.swp
 \#*
 *~
+
+.gradle
+
 # IntelliJ files
 *.eml
 *.ipr
@@ -27,8 +30,11 @@
 __pycache__
 ant.properties
 bin
+
 build
+build2
 cachedir
 dist
+
 profile.txt
 out
diff --git a/build.gradle b/build.gradle
new file mode 100644
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,755 @@
+/*
+ * Gradle build for Jython. See also settings.gradle.
+ *
+ * This is an attempt to build a distributable JAR using Gradle that could be
+ * cited as a dependency by other Gradle or Maven projects, when they use the
+ * Jython interpreter from Java (under JSR-223 or directly).
+ *
+ * At present, the build is additional to the Ant build that remains the
+ * primary and reliable support for development, for test, and to build the
+ * Jython installers.
+ *
+ * The delivered jar should contain only Jython project material (Java classes
+ * and the Python library) while the many JARs Jython depends on will be cited
+ * in the accompanying metadata as dependencies.
+ *
+ * The Jython source structure does not follow the standard convention for
+ * Gradle. This script deals with that without changing it, but it uses a build
+ * directory (build2) entirely separate from Ant's, in which generated and
+ * compiled material is posted conformant with Gradle conventions. This means
+ * that the later tasks Gradle provides (test and jar) do not need so much
+ * customisation.
+ */
+
+plugins {
+    id 'java-library'
+    id 'antlr'
+    // XXX Add maven and use it.
+}
+
+import java.text.SimpleDateFormat
+
+// ---------------- Determine the version of Jython ----------------------------
+
+/*
+ * This one string will be used to name the generated JAR and version-stamp the
+ * application. It should be all you have to edit to version a release built
+ * here. But of course you have to do it the hard way too (see build.xml) as
+ * long as Ant is also used.
+ */
+// <major> . <minor> ( . <micro> )? ( <release> <serial> )? ([-+] <word>? )?
+
+version = '2.7.2a1+'
+
+// Valid examples (please preserve in comments):
+//version = '2.7.2a2'
+//version = '2.7.2b1'
+//version = '2.7.2rc1'
+//version = '2.7.2'
+
+
+// ---------------- Miscellaneous configuration --------------------------------
+
+
+// Separate the Gradle build from that of Ant
+buildDir = file('build2')
+ext {
+    buildDate = new Date()
+    // Java source generated by ANTLR
+    antlrGenDir = "$buildDir/gensrc/org/python/antlr"
+    // This is where we assemble the standard library pre-JAR
+    buildLibDir = "$buildDir/resources/main/Lib/"
+    compiledLibDir = "$buildDir/classes/main/Lib/"
+}
+
+
+repositories {
+    /*
+     * Jython is distributed through Maven Central. Get our dependencies there
+     * too.
+     */
+    mavenCentral()
+}
+
+sourceSets {
+
+    main {  // Non-standard locations must be specified explicitly
+
+        antlr {
+            srcDirs = ['grammar']
+            exclude 'Base.g' // Not used (and produces errors)
+        }
+
+        java {
+            srcDirs = ['src', project.ext.antlrGenDir]
+            exclude 'com/**'    // for now
+        }
+
+        // output.resourcesDir = project.ext.assemblyDir
+
+        resources {
+            // Resources in project root, but this invites an explosion:
+            // srcDirs = ['']
+            // ... so claim no sources:
+            srcDirs = []
+            // and fix it in task processResources
+        }
+    }
+
+    test {  // Non-standard locations must be specified explicitly
+
+        java {
+            srcDirs = ['tests/java']
+            exclude 'com/**'    // XXX for now
+        }
+    }
+}
+
+dependencies {
+    /*
+     * These must correspond fairly exactly with the external libraries (JARs)
+     * mentioned in the Ant build.xml.
+     */
+
+    // Using a version available from repo (not 'extlibs/servlet-api-2.5' as in build.xml)
+    implementation group: 'javax.servlet', name: 'javax.servlet-api', version: '3.1.0'
+
+    // implementation 'mysql-connector-java-5.1.42-bin'
+    // implementation 'postgresql-42.1.1.jre7'
+
+    // pin to Antlr 3.1.3 until we upgrade parsing
+    antlr 'org.antlr:antlr:3.1.3' // use ANTLR version 3
+    implementation 'org.antlr:antlr-runtime:3.1.3'
+    implementation 'org.antlr:stringtemplate:3.2.1'
+
+    implementation group: 'org.apache.commons', name: 'commons-compress', version: '1.14'
+
+    // pin to ASM 5.2 until we upgrade compilation
+    implementation group: 'org.ow2.asm', name: 'asm', version: '5.2'
+    implementation group: 'org.ow2.asm', name: 'asm-commons', version: '5.2'
+    implementation group: 'org.ow2.asm', name: 'asm-util', version: '5.2'
+
+    implementation group: 'com.google.guava', name: 'guava', version: '22.0-android'
+    implementation group: 'com.ibm.icu', name: 'icu4j', version: '59.1'
+
+    implementation group: 'com.carrotsearch', name: 'java-sizeof', version: '0.0.5'
+
+    implementation group: 'com.github.jnr', name: 'jffi', version: '1.2.16'
+    implementation group: 'com.github.jnr', name: 'jnr-netdb', version: '1.1.6'
+    implementation group: 'com.github.jnr', name: 'jnr-ffi', version: '2.1.7'
+    implementation group: 'com.github.jnr', name: 'jnr-posix', version: '3.0.44'
+    implementation group: 'com.github.jnr', name: 'jnr-constants', version: '0.9.9'
+
+    implementation group: 'jline', name: 'jline', version: '2.14.5'
+
+    implementation group: 'io.netty', name: 'netty-buffer', version: '4.1.24.Final'
+    implementation group: 'io.netty', name: 'netty-codec', version: '4.1.24.Final'
+    implementation group: 'io.netty', name: 'netty-common', version: '4.1.24.Final'
+    implementation group: 'io.netty', name: 'netty-handler', version: '4.1.24.Final'
+    implementation group: 'io.netty', name: 'netty-resolver', version: '4.1.24.Final'
+    implementation group: 'io.netty', name: 'netty-transport', version: '4.1.24.Final'
+
+    // Used implicitly in the Ant build, must be explicit here
+    implementation group: 'org.apache.ant', name: 'ant', version: '1.9.7'
+
+    testImplementation group: 'junit', name: 'junit', version: '4.10'
+
+}
+
+// ---------------- Resource Processing ----------------------------------------
+
+/*
+ * Jython brings several files we could treat as resources, but they do not sit
+ * in the Gradle-conventional 'main/resources' directory, rather are in the
+ * project root or rub shoulders with the java source. Pick them individually.
+ */
+processResources {
+    from(file('.')) {
+        include 'LICENSE.txt'
+    }
+    from(file('src')) {
+        include 'META-INF/**'
+        include 'org/python/modules/ucnhash.dat'
+    }
+}
+
+// ---------------- ANTLR Task -------------------------------------------------
+
+generateGrammarSource {
+    maxHeapSize = "512m"
+    outputDirectory = file(project.ext.antlrGenDir)
+}
+
+// ---------------- Expose Task ------------------------------------------------
+
+/*
+ * The exposer operates between two (somewhat fixed) directories. We follow
+ * the Gradle-conventional directory structure (not the legacy one).
+ */
+ext {
+    compileDir = "$buildDir/classes/java/main/"
+    exposedDir = "$buildDir/classes/exposed/main/"
+}
+
+configurations {
+    expose.extendsFrom(implementation)
+}
+
+dependencies {
+    // Put our compiled classes on the path of the expose (Ant) task
+    expose files("$buildDir/classes/java/main")
+}
+
+// A (Gradle) task to run the Ant task 'expose'.
+task expose (group: 'Custom', dependsOn: compileJava) {
+
+    description = 'Expose Java types to Python using their annotations.'
+
+    // Allow Gradle to infer the need to regenreate the outputs
+    inputs.files(fileTree("${project.ext.compileDir}/org/python"))
+    outputs.dir(project.ext.exposedDir)
+
+    doLast {
+        /*
+         * Define an Ant task called 'expose' in the project's AntBuilder.
+         * We can't define it until ExposeTask has been compiled.
+         */
+        ant.taskdef(
+            name: 'expose',
+            classname: 'org.python.expose.generate.ExposeTask',
+            classpath: configurations.expose.asPath
+         )
+
+        // Use the Gradle-conventional directory structure (not the legacy one).
+        ant.expose(
+            srcdir: file(project.ext.compileDir),
+            destdir: mkdir(file(project.ext.exposedDir)),
+            includesfile: file('CoreExposed.includes')
+        )
+    }
+}
+
+// ---------------- Version-related file generation ----------------------------
+
+/*
+ * Write the information that org.python.Version reads from
+ * org/python/version.properties in the class file structure. The inputs to
+ * this are: information from Mercurial (hg command required); project.version;
+ * and project.ext.buildDate. The task works quite hard to decode
+ * project.version, which must have the correct form, to deduce whether you
+ * really intend this to be a release. If anything comes after the release
+ * number, typically it's a '+' sign, the version becomes a snapshot.
+ */
+task generateVersionInfo(
+        type: WriteProperties,
+        description: 'Write the version information as properties') {
+
+    outputFile = file("${processResources.destinationDir}/org/python/version.properties")
+    comment = ' Jython version information (from build.gradle)'
+
+    // Create the properties when the task runs. But do it before the write!
+    doFirst {
+        /*
+         * Query Mercurial for version and tagging.
+         */
+        String hgOutput = 'hg identify -ibt'.execute().text
+        hgOutput = hgOutput.split('\n', 2)[0]
+
+        // <revision-id>(+)? <branch> <tag>
+        String[] parts = hgOutput.split(/\s+/, 3)
+        if (parts.length != 3) {
+            throw new IllegalArgumentException(
+                    "Cannot split Mercurial output '$hgOutput' into 3")
+        }
+        def (ident, branch, tag) = parts
+        property('jython.build.hg_branch', branch)
+        property('jython.build.hg_tag', tag)
+        property('jython.build.hg_version', ident)
+
+        /*
+         * Decompose the version string into elements for Jython to access as
+         * properties. (The Ant build.xml requires them to be set in parts, but
+         * we can work it out from the .)
+         */
+        // <major>.<minor>(.<micro>)(<release><serial>)?([-+]<snapshot>)?
+        def versionRegex = /(\d+)\.(\d+)(\.(\d+))?((a|b|rc)(\d+))?([-+]\w*)?/
+        def versionMatcher = project.version =~ versionRegex
+        if (versionMatcher.count != 1) {
+            throw new IllegalArgumentException(
+                    "Cannot parse project version string '${project.version}'")
+        }
+        // In principle it could match more than once: take the leftmost
+        def versionResult = versionMatcher[0]
+
+
+        // Useful debug
+        /*
+        for (int i=0; i < versionResult.size(); i++) {
+            String part = versionResult[i]
+            println "versionResult[$i] = $part"
+        } */
+
+        // <major>.<minor> means <major>.<minor>.0
+        String major = versionResult[1]
+        String minor = versionResult[2]
+        String micro = versionResult[3] ? versionResult[4] : '0'
+
+        // Convert the optional <release><serial> to numbers
+        int SNAPSHOT = 0xaa
+        int level = 0, serial = 0
+        if (versionResult[5]) {
+            // This is some kind of pre-final release (unless snapshaot)
+            serial = versionResult[7] as int
+            switch (versionResult[6]) {
+                case 'a': level = 0xa; break // ALPHA release
+                case 'b': level = 0xb; break // BETA release
+                case 'rc': level = 0xc; break // release candidate
+            }
+        } else {
+            // Not marked as a/b/rc so ostensibly a final release.
+            level = 0xf
+        }
+
+        // Except, if there was something after the version we decoded ...
+        if (versionResult[8]) {
+            level = SNAPSHOT // it's snapshot or dev version of some kind
+            serial = 0
+        }
+
+        property('jython.version', project.version)
+        property('jython.major_version', major)
+        property('jython.minor_version', minor)
+        property('jython.micro_version', micro)
+        property('jython.release_level', level)
+        property('jython.release_serial', serial)
+
+        /*
+         * Time-stamp the build. In the time part, the ':' gets escaped to
+         * '\:', consistent with Properties.store(), unlike the Ant build.
+         */
+        property('jython.build.time',
+                (new SimpleDateFormat('HH:mm:ss'))
+                .format(project.ext.buildDate))
+        property('jython.build.date',
+                (new SimpleDateFormat('MMM d yyyy'))
+                .format(project.ext.buildDate))
+
+        /*
+         * Remind the developer about tagging it if it looks like a release,
+         * or to adjust project.version if we're moving on from the release.
+         */
+        if (level != SNAPSHOT) {
+            def L = [0:'', 10:'a', 11:'b', 12:'rc', 15:'']
+            String release = "$major.$minor.$micro${L[level]}${serial?:''}"
+            println "This build is versioned for distribution as $release"
+            if (tag == 'tip' || ident.endsWith('+')) {
+                println "If this really is distributable, " +
+                        "don't forget to tag it in the repository.\n" +
+                        "Alternatively, add a suffix to version = " +
+                        "'${project.version}' in build.gradle to shut this up."
+            }
+        }
+    }
+}
+
+// Attach this task to processResources
+processResources.dependsOn(generateVersionInfo)
+
+
+// ---------------- Copy Python Library ----------------------------------------
+
+/*
+ * The default behaviour of the Java plug-in is to make a JAR of the classes in
+ * the "main" source set. We need a more complex assembly that provides users
+ * with exposed classes instead of their plain counterparts, and also various
+ * configuration files and the Python library.
+ *
+ * These copies include the tests, so we can test things :), but a subsequent
+ * JarTask of the build should exclude them as necessary.
+ */
+
+ext {
+    libPython = 'lib-python/2.7'
+    libJython = 'Lib'
+}
+
+
+/*
+ * Copy the Python standard library. We take this from a distribution of
+ * CPython, but take only the files specified in CPythonLib.includes in the
+ * project root.
+ */
+task copyLib(
+        type: Copy,
+        description: 'Merge lib-python and Jython Lib during assembly') {
+
+    into "${project.ext.buildLibDir}"
+
+    // Copy Jython Lib, with precedence over CPython files of the same name
+    from file(project.ext.libJython)
+    exclude 'test/'
+    exclude '**/*.class'
+    duplicatesStrategy = DuplicatesStrategy.INCLUDE
+
+    // Allow Gradle to infer the need to regenerate the outputs
+    inputs.dir project.ext.libJython
+    inputs.dir project.ext.libPython
+    inputs.file file('CPythonLib.includes')
+    outputs.dir project.ext.buildLibDir
+
+    doFirst {
+        // Select the CPython stdlib files by making a list.
+        def cPythonLibIncludes = []
+        // Read list from CPythonLib.includes, stripping comments and spaces.
+        file('CPythonLib.includes').eachLine { line ->
+            def trimmed = line.split('#', 2)[0].trim()
+            if (trimmed.length() > 0) {
+                cPythonLibIncludes << trimmed
+            }
+        }
+        // Copy the subset as specified by the list
+        project.copy {
+            from file(project.ext.libPython)
+            include cPythonLibIncludes
+            exclude '**/*.pyc', '**/*.pyd'
+            into project.ext.buildLibDir
+            duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+        }
+    }
+
+    /*
+    <target name="copy-cpythonlib">
+        <copy todir="${dist.dir}/Lib">
+            <fileset dir="${python.lib}" excludes="** /*.pyc, ** /*.pyo"
+                    includesfile="${jython.base.dir}/CPythonLib.includes">
+                <!-- The include file gets all of lib-python/2.7's test directory, but we only want the ones from Jython's Lib.   -->
+                <present present="srconly" targetdir="${jython.base.dir}/Lib"/>
+            </fileset>
+        </copy>
+    </target>
+    */
+}
+
+
+
+
+// ---------------- Jython-Compile Python --------------------------------------
+
+/*
+ * Compile the Python modules to .class files for the JAR. Whereas Jython runs
+ * happily with a concrete Lib folder, creating and caching the .class files,
+ * when Jython is supplied as a JAR, we prefer to compile the class files once
+ * in advance.
+ */
+
+configurations {
+    pycompile.extendsFrom(implementation)
+}
+
+dependencies {
+    // Jython as built so far should be on the path of the jycompile (Ant) task
+    pycompile files("$buildDir/classes/exposed/main")
+    pycompile files("$buildDir/classes/java/main")
+    pycompile files("$buildDir/resources/main")
+}
+
+// A (Gradle) task to run the Ant task 'jycompile' (not pycompile).
+task pycompile(
+        group: 'Custom',
+        description: 'Compile the Python modules to .class files for the JAR') {
+
+    dependsOn compileJava
+    dependsOn expose
+    dependsOn copyLib
+
+    // Allow Gradle to infer the need to regenerate the outputs
+    inputs.dir project.ext.buildLibDir
+    outputs.dir project.ext.compiledLibDir
+
+    doFirst {
+        /*
+         * Define an Ant task called 'jycompile' in the project's AntBuilder.
+         * We can't define it until JythoncAntTask has been compiled, so this
+         * must happen during the execution of the task (early).
+         */
+         ant.taskdef(
+            name: 'jycompile',
+            classname: 'org.python.util.JycompileAntTask',
+            classpath: configurations.pycompile.asPath
+         )
+    }
+
+    doLast {
+        /*
+         * Now use the 'jycompile' Ant task tocompile the Python source we
+         * supply to users. The exclusions are copied from build.xml, as also
+         * is this comment:
+            <!-- One might think that the exclusion of lib2to3/tests/** is
+                 recursive, but one would be wrong ;) It's actually only
+                 two levels, so for now the workaround is to also include
+                 data/myfixes/**
+
+                 This exclusion for lib2to3/tests/ in general is necessary
+                 because data/infinite_recursion.py is not compileable by
+                 Jython - it's too large and will exceed Java method
+                 limits for the top level script; nor is
+                 data/py3_test_grammar.py - it's Python 3. Meanwhile
+                 refactor.get_all_fix_names depends on having *.py, not
+                 exclusively $py.class, files available in
+                 lib2to3/tests/data/myfixes/**. -->
+         */
+        def exclusions = ['test/**', 'lib2to3/tests/**',
+            'lib2to3/tests/data/myfixes/**']
+        ant.jycompile(
+            srcdir: project.ext.buildLibDir,
+            destdir: project.ext.compiledLibDir,
+            excludes: exclusions.join(',')    // Yes, it's that way round :o
+        )
+    }
+
+}
+
+
+// ---------------- Building the JAR -------------------------------------------
+
+/*
+ * The default behaviour of the Java plug-in is to make a JAR of the classes in
+ * the "main" source set. We need a more complex operation that provides users
+ * with exposed classes instead of their plain counterparts, and also various
+ * configuration files and the Python library.
+ *
+ * Much of the assembly has taken place already in selective copying to the
+ * build directory by tasks processResources and copyLib.
+ */
+
+task jar(type: Jar, overwrite: true) {
+
+    dependsOn pycompile
+
+    /*
+     * This is a custom replacement Jar task so that we may control the
+     * order of adding classes. Exposed versions of identically-named classes
+     * supersede (by arriving first) those directly from compilation.
+     */
+    exclude 'org/python/expose/generate/**' // The expose tool itself
+
+    // Add the exposed classes to the JAR first
+    from expose
+
+    // Add other compiled classes but without overwriting the exposed ones
+    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+    from compileJava
+
+    // Add the resources
+    from processResources
+
+    // Add Python library
+    preserveFileTimestamps = true
+    from file(project.ext.buildLibDir).parent
+    from file(project.ext.compiledLibDir).parent
+
+    manifest {
+        // These attribute values are based on inspecting the ant build
+        attributes ([
+            'Main-Class': 'org.python.util.jython',
+            'Built-By': 'Mistake',
+        ])
+
+        attributes( [ // Build-Info section
+            'version': project.version,
+            'build-compiler': 'modern',
+            'jdk-target-version': '1.7',
+            'debug': true,
+        ], 'Build-Info' )
+    }
+
+}
+
+
+// ---------------- Java unit tests --------------------------------------------
+
+ext {
+    //distDir = relativePath("$buildDir/assembly")
+    testSourceDir = relativePath('tests/java')
+}
+
+
+dependencies {
+    // Put the exposed classes on the path of the test tasks
+    testImplementation files(expose)
+}
+
+// Ensure exposed classes are ahead of standard path
+sourceSets.test {
+    compileClasspath  = files(expose.outputs) + compileClasspath
+    runtimeClasspath = files(expose.outputs) + runtimeClasspath
+    // println "runtimeClasspath = ${runtimeClasspath.asPath}"
+}
+
+compileTestJava {
+    dependsOn expose
+}
+
+test {
+
+    dependsOn copyLib
+
+    // Stop on first test failure
+    failFast = true
+
+    // Properties as defined in Ant target javatest-basepath
+    //systemProperty 'python.home', project.ext.distDir
+    // XXX Not sure of all that python.home is used for in tests.
+    systemProperty 'python.home', file(copyLib.destinationDir).parent
+    systemProperty 'python.test.source.dir', project.ext.testSourceDir
+    // Place cache outside the targets for jar task
+    systemProperty 'python.cachedir', "${project.buildDir}/cachedir"
+
+    // Include/exclude based on Ant target javatest-basepath
+    include '**/*Test*'
+    exclude '**/InterpTestCase'
+    exclude '**/jythonTest*'            // Must run interactively
+    exclude 'org/python/antlr/**'
+    exclude 'org/python/tests/imp/**'   // See build.xml:importest
+
+    // Some additional exclusions or else the task fails
+    // FIXME: leaves stdin/out/err as PyFileWriter that has no fileno()
+    // causing _ioTest to fail.
+    exclude '**/jsr223/*'
+    // FIXME: Tests that hard-code directory paths (use a symbol):
+    exclude 'org/python/compiler/custom_proxymaker/**'
+    exclude 'org/python/compiler/JavaMakerSmokeTest.class'
+    // FIXME: Failing test finds project root from test class location
+    exclude 'org/python/core/PySystemState_registry_Test.class'
+    // FIXME: Fails as sys._jy_console not set when run under Gradle
+    exclude 'org/python/util/InterpreterTest.class'
+    // FIXME: Failing test, see issue 2410
+    exclude 'org/python/core/PySystemStateTest.class'
+
+    doFirst {
+        println "systemProperties = $systemProperties"
+    }
+
+    /* From build.xml :
+
+    <target name="javatest-basepath" depends="developer-build">
+        <mkdir dir="${junit.reports}"/>
+        <junit fork="true" printsummary="true">
+            <formatter type="xml"/>
+            <sysproperty key="python.home" value="${dist.dir}"/>
+            <sysproperty key="python.test.source.dir" value="${test.source.dir}"/>
+            <classpath refid="test.classpath"/>
+            <batchtest todir="${junit.reports}" skipNonTests="true">
+                <fileset dir="${test.source.dir}" includes="** /*Test*.java">
+                    <exclude name="** /InterpTestCase.java" />
+                    <exclude name="** /jythonTest*" /> <!-- Must run interactively -->
+                    <exclude name="org/python/antlr/**" />
+                    <exclude name="org/python/tests/imp/**" /> <!-- See importest -->
+                    <exclude name=".classpath" />
+                    <exclude name=".project" />
+                </fileset>
+            </batchtest>
+        </junit>
+    </target>
+
+    <target name="importest" depends="developer-build" description="run all the JUnit tests that need tests/python in the path.">
+        <mkdir dir="${junit.reports}"/>
+        <junit fork="true" printsummary="true">
+            <formatter type="xml"/>
+            <sysproperty key="python.home" value="${dist.dir}"/>
+            <sysproperty key="python.test.source.dir" value="${test.source.dir}"/>
+            <classpath refid="test.classpath"/>
+            <classpath refid="test.classpath"/>
+            <classpath>
+                <pathelement location="${jython.base.dir}/tests/python"/>
+            </classpath>
+            <batchtest todir="${junit.reports}">
+                <fileset dir="${test.source.dir}" includes="org/python/tests/imp/*Test*.java">
+                </fileset>
+            </batchtest>
+        </junit>
+    </target>
+
+    */
+}
+
+// ---------------- Miscellaneous fettling of the prepare phase ----------------
+
+// Source is globally UTF-8 (well, nearly).
+tasks.withType(JavaCompile) {
+    options.encoding = "UTF-8"
+}
+
+
+
+// ---------------- Tasks for debugging ----------------------------------------
+
+
+task dumpCP {
+    doLast {
+        //println('configurations.testCompile:')
+        //configurations.testCompile.each { println it }
+        //println('configurations.testRuntime:')
+        //configurations.testRuntime.each { println it }
+        println('configurations.expose:')
+        configurations.expose.each { println it }
+        println('configurations.pycompile:')
+        configurations.pycompile.each { println it }
+    }
+}
+
+
+task dumpex {
+    doLast {
+        int n = project.ext.exposedDir.length()
+        Set<String> exposedClasses = new TreeSet()
+        //println "*** files in ${project.ext.exposedDir}:"
+        for (f in fileTree(project.ext.exposedDir)) {
+            //println project.relativePath(f).substring(n)
+            exposedClasses.add( project.relativePath(f).substring(n) )
+        }
+        //for (f in exposedClasses) { println f }
+
+        println "${fileTree(project.ext.compileDir).size()} compiled classes."
+
+        n = project.ext.compileDir.length()
+        int countx = 0
+        for (f in fileTree(project.ext.compileDir)) {
+            //println project.relativePath(f).substring(n)
+            String name = project.relativePath(f).substring(n)
+            if (name in exposedClasses) { countx += 1 }
+        }
+        println "${exposedClasses.size()} classes from ${countx} exposed."
+
+        def compiledToJar = fileTree(project.ext.compileDir).filter({
+            File f -> !(project.relativePath(f).substring(n) in exposedClasses)
+        })
+
+        println "${compiledToJar.size()} to be jarred (after filtering)."
+
+        int counti = 0
+        for (f in fileTree(project.ext.compileDir)) {
+            String name = project.relativePath(f).substring(n)
+            String exposed = (name in exposedClasses) ? "EXPOSED" : ""
+            // println "${name} ${exposed}"
+            if (exposed) { counti += 1 }
+        }
+
+        println "${counti} in overlap."
+    }
+}
+
+
+task dump {
+    doLast {
+        // Debug
+        println '*** source sets ***'
+        for ( sourceSet in sourceSets ) {
+            println "  ${sourceSet}"
+            // for ( name in sourceSet.asMap.keys ) {
+                // sourceDirectorySet = sourceSet.asMap[name]
+                // println "    $name = $sourceDirectorySet"
+            // }
+        }
+    }
+}
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..91ca28c8b802289c3a438766657a5e98f20eff03
GIT binary patch
[stripped]
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100644
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+ at if "%DEBUG%" == "" @echo off
+ at rem ##########################################################################
+ at rem
+ at rem  Gradle startup script for Windows
+ at rem
+ at rem ##########################################################################
+
+ at rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+ at rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+ at rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+ at rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+ at rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+ at rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+ at rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+ at rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,5 @@
+/*
+ * Gradle settings for Jython. See also build.gradle.
+ */
+
+rootProject.name = 'jython'
diff --git a/tests/java/org/python/core/BaseBytesTest.java b/tests/java/org/python/core/BaseBytesTest.java
--- a/tests/java/org/python/core/BaseBytesTest.java
+++ b/tests/java/org/python/core/BaseBytesTest.java
@@ -217,7 +217,7 @@
         // Local constructor from byte[]
         int[] aRef = toInts("Chaque coquillage incrusté");
         BaseBytes a = getInstance(aRef);
-        System.out.println(toString(a));
+        // System.out.println(toString(a));
         assertEquals(aRef.length, a.size());
 
         // init(int) at various sizes
@@ -237,7 +237,7 @@
         BaseBytes a = getInstance(aRef);
         // Copy constructor b = bytes(a)
         BaseBytes b = getInstance(a);
-        System.out.println(toString(b));
+        // System.out.println(toString(b));
         assertEquals(a.size(), b.size());
         // assertEquals(a.storage, b.storage); // Supposed to share?
         // Check we got the same bytes
@@ -254,7 +254,7 @@
         // Make an Iterable<? extends PyObject> of that
         Iterable<? extends PyObject> ia = iterableBytes(aRef);
         BaseBytes a = getInstance(ia);
-        System.out.println(toString(a));
+        // System.out.println(toString(a));
         assertEquals(aRef.length, a.size());
         checkInts(aRef, a);
 
@@ -319,7 +319,7 @@
             PyObject aRef = boobyPrize[dip];
             try {
                 BaseBytes a = getInstance(brantub[dip]);
-                System.out.println(toString(a));
+                // System.out.println(toString(a));
                 fail("Exception not thrown for " + brantub[dip]);
             } catch (PyException pye) {
                 // System.out.println(pye);
@@ -452,7 +452,7 @@
 
         try {
             a.pyset(start, x);
-            System.out.println(toString(a));
+            // System.out.println(toString(a));
             fail(String.format("Exception not thrown for pyset(%d,%s)", start, x));
         } catch (PyException pye) {
             // System.out.println(pye);
@@ -476,7 +476,7 @@
 
         try {
             a.setslice(start, stop, step, x);
-            System.out.println(toString(a));
+            // System.out.println(toString(a));
             fail(String.format("Exception not thrown for setslice(%d,%d,%d,%s)", start, stop, step,
                     x));
         } catch (PyException pye) {
diff --git a/tests/java/org/python/core/PyBufferTest.java b/tests/java/org/python/core/PyBufferTest.java
--- a/tests/java/org/python/core/PyBufferTest.java
+++ b/tests/java/org/python/core/PyBufferTest.java
@@ -60,7 +60,7 @@
     protected int verbosity = 0;
 
     /** Print a list of the test material. (From JUnit 4.12 use Parameters(name)). */
-    protected static final boolean PRINT_KEY = true;
+    protected static final boolean PRINT_KEY = false;
 
     /** Size of some large arrays. */
     static final int LONG = 1000;
diff --git a/tests/java/org/python/core/PyByteArrayTest.java b/tests/java/org/python/core/PyByteArrayTest.java
--- a/tests/java/org/python/core/PyByteArrayTest.java
+++ b/tests/java/org/python/core/PyByteArrayTest.java
@@ -12,6 +12,9 @@
  */
 public class PyByteArrayTest extends BaseBytesTest {
 
+    /** This program may be used to display operation time, but this is not necessary for tests. */
+    final static boolean SHOW_OPERATION_TIMES = false;
+
     /**
      * Constructor required by JUnit.
      *
@@ -963,11 +966,13 @@
      * slice to replace is simple and contiguous (2-argument slice).
      */
     public void testSetsliceTime() {
-        int verbose = 1;
-        timeSetslice(50, 100, SMALL, 2 * SMALL, verbose);
-        timeSetslice(50, 100, MEDIUM, MEDIUM, verbose);
-        timeSetslice(500, 20, LARGE, LARGE / 5, verbose);
-        // timeSetslice(1000, 4, HUGE, HUGE/5, verbose);
+        if (SHOW_OPERATION_TIMES) {
+            int verbose = 1;
+            timeSetslice(50, 100, SMALL, 2 * SMALL, verbose);
+            timeSetslice(50, 100, MEDIUM, MEDIUM, verbose);
+            timeSetslice(500, 20, LARGE, LARGE / 5, verbose);
+            timeSetslice(1000, 4, HUGE, HUGE/5, verbose);
+        }
     }
 
     /**
@@ -1388,11 +1393,13 @@
      * slice to replace is extended (3-argument slice).
      */
     public void testDelsliceTime3() {
-        int verbose = 1;
-        timeDelslice3(50, 100, SMALL, verbose);
-        timeDelslice3(50, 100, MEDIUM, verbose);
-        timeDelslice3(20, 4, LARGE, verbose);
-        // timeDelslice3(10, 1, HUGE, verbose);
+        if (SHOW_OPERATION_TIMES) {
+            int verbose = 1;
+            timeDelslice3(50, 100, SMALL, verbose);
+            timeDelslice3(50, 100, MEDIUM, verbose);
+            timeDelslice3(20, 4, LARGE, verbose);
+            timeDelslice3(10, 1, HUGE, verbose);
+        }
     }
 
     /**

-- 
Repository URL: https://hg.python.org/jython


More information about the Jython-checkins mailing list