Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Gabriel Selzer
    @gselzer
    @ctrueden writing a SciJava Ops Engine integration test now, what is the preferred package structure for those?
    I currently have src/it/discovery-test, should I put the tests in there?
    Gabriel Selzer
    @gselzer
    Well, I'll write them now in src/test/java, we can move them later
    17 replies
    Gabriel Selzer
    @gselzer

    So I currently have regression tests for:

    • Determining the number of Ops/OpInfos discoverable using ServiceLoader
    • Determining the number of OpCollections/OpInfos discoverable using ServiceLoader
    • Determining the number of Ops/OpInfos discoverable using Therapi (this number is currently zero)

    Do we want a matching regression test? If so, what Ops should be tested? There are some math Ops which make sense to test, but what about adapt Ops? simplify Ops?

    10 replies
    Time to switch ImageJ Ops2 over to Therapi!
    Gabriel Selzer
    @gselzer
    @ctrueden I think you'll be proud of this :smiley: scijava/incubator@c23f4ab
    8 replies
    Will finish tomorrow
    Giuseppe Barbieri
    @elect86
    @gselzer I can provide you an easy kotlin script for that, what do you want to achieve exactly? All the reference for each file under imagej/imagej-ops2/ switching double quote with single quote, and what about priority?
    Giuseppe Barbieri
    @elect86
    Screenshot from 2021-11-12 07-15-11.png
    Gabriel Selzer
    @gselzer

    Will finish tomorrow

    Nearly finished, a couple tests broke when I migrated OpFields to therapi generation. I'll have to finish next week

    See scijava/incubator@94523aa for progress
    Curtis Rueden
    @ctrueden
    1 reply
    Giuseppe Barbieri
    @elect86
    what about merging all the scijava-core and fiji-core plugins in one project each?
    Since they are quite simple and small, I think this might make sense, or?
    13 replies
    Gabriel Selzer
    @gselzer
    @ctrueden the incubator works just fine with SciJava Maven Plugin
    Going to do the rebasing now
    Gabriel Selzer
    @gselzer
    Done
    Gabriel Selzer
    @gselzer
    @ctrueden I'm not sure I quite like our Discoverer.all() method; can you see a way that we can include a Service-Loader based Discoverer (i.e. the output of Discoverer.using()) in the return?
        public static Iterable<Discoverer> all(Function<Class<Discoverer>, ? extends ServiceLoader<Discoverer>> func) {
            return (ServiceLoader<Discoverer>) func.apply(Discoverer.class);
        }
    It would be slick if we could enforce broader generics on that discoverer
    Gabriel Selzer
    @gselzer
    I'm thinking this will work?
        static <T> Iterable<Discoverer> all(Function<Class<T>, ? extends ServiceLoader<T>> func) {
            try {
                ServiceLoader<Discoverer> d = (ServiceLoader<Discoverer>) func.apply((Class<T>) Discoverer.class);
                List<Discoverer> list = d.stream().map(p -> p.get()).collect(Collectors.toList());
                list.add(Discoverer.using(func));
                return list;
            } catch (ClassCastException e) {
                return Collections.emptyList();
            } catch (ServiceConfigurationError e) {
                return Collections.emptyList();
            }
        }
    67 replies
    Giuseppe Barbieri
    @elect86
    want to give classgraph a try?
    Gabriel Selzer
    @gselzer
    @elect86 that would not solve the problem we are dealing with there
    Curtis Rueden
    @ctrueden
    I do think it would be fun to write a Discoverer backed by classgraph, though.
    Gabriel Selzer
    @gselzer
    As an aside, if you would like to make a ClassgraphDiscoverer, please declare it as a Service in the module-info

    I do think it would be fun to write a Discoverer backed by classgraph, though.

    Right, yeah. I just meant that it would not fix the problem we were talking about yesterday

    Curtis Rueden
    @ctrueden
    public class ClassGraphDiscoverer implements Discoverer {
      @Override   
      public <T> List<T> discover(Class<T> type) {
        List<T> instances = new ArrayList<>();
        try (ScanResult scanResult = new ClassGraph().enableAllInfo().scan()) {
          ClassInfoList impls = scanResult.getSubclasses(type);
          for (ClassInfo impl : impls) {
            try {
              Class<?> c = impl.loadClass();
              if (!type.isAssignableFrom(c))) continue; // Not an implementation of the requested type.
              T instance = (T) c.newInstance();
              instances.add(instance);
            }
            catch (IllegalArgumentException exc) {
              // NB: Could not load the class.
              // TODO: Log the exception.
            }
            catch (ExceptionTypesThatNewInstanceThrows exc) {
              // NB: Could not instantiate the class.
              // TODO: Log the exception.
            }
          }
        }
        return instances;
      }
    }
    Note that the above is completely untested. @elect86 Let us know if there is a better approach to using classgraph for this. In particular, I'm concerned that every call to discover may rescan the classpath (‽).
    Another concern is that getSubclasses may return abstract layers, not only "leaf class" implementations. So probably more checking is needed here before trying to instantiate each class. Maybe also checking for a no-args constructor? I dunno.
    I feel like classgraph must offer an easier way to do this, a la the ServiceLoader API, but I wasn't seeing it in the docs.
    Giuseppe Barbieri
    @elect86
    Can you guide me? @gselzer can you link me an example declared as a Service in module-info?
    @ctrueden the simplest test ever to copy/paste?
    on a side note, Kotlin has nice TODO(reason: String) :D
    Curtis Rueden
    @ctrueden

    @elect86 wrote:

    Can you guide me?

    I don't know classgraph, I thought you did. That's why I asked for your opinion. The question is: how do you get back one instance each of all implementing classes of a particular interface.

    Giuseppe Barbieri
    @elect86
    no, I meant if you can guide me into scijava
    Curtis Rueden
    @ctrueden
    In this case there's nothing to guide—it's a pure classgraph question.
    Giuseppe Barbieri
    @elect86
    ok, I can provide a PR, any info about tests?
    Curtis Rueden
    @ctrueden
    I'm not asking for a PR. Just whether you think the code I put above is a good way to use classgraph to solve that problem. Or if there is some API I missed.
    Giuseppe Barbieri
    @elect86
    it looks fine
    Curtis Rueden
    @ctrueden
    It's how you would do it?
    Giuseppe Barbieri
    @elect86
    you can tune the scan, but are we talking about an Annotation or?
    Curtis Rueden
    @ctrueden
    For now let's say no annotation.
    Will the try-with-resources result in a new classpath scan per discover call? Or does classgraph cache things?
    Giuseppe Barbieri
    @elect86
    as far as I recall, the scan is the bottleneck, so the less, the better
    ideally, you'd do this just once at the begin and then re-use it whenever you want to extract anything
    Curtis Rueden
    @ctrueden
    Agreed, but I wasn't sure if it was OK to save the ScanResult as a field of the Discoverer. That goes against the classgraph docs which say you should dispose of your ScanResult ASAP.
    Giuseppe Barbieri
    @elect86
    indeed, there seems to be some allocated resources alongside..
    Gabriel Selzer
    @gselzer
    @ctrueden I think this looks great.

    ideally, you'd do this just once at the begin and then re-use it whenever you want to extract anything

    I think at the end of the day you are going to be caching the results of the discover call, so I can't see a situation where you're going to be calling discover enough times to be worried about this?

    Curtis Rueden
    @ctrueden
    I'm worried about calling discover(Something.class) and then discover(SomethingElse.class) and then discover(AThirdThing.class) causing three full classpath scans.
    Gabriel Selzer
    @gselzer
    We could write some fancy logic to time it out after a couple seconds?