Pkg.add refactoring proposal

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Pkg.add refactoring proposal

Rory Finnegan
Hi there,

I'm working at a company that needs to add some features to julia's pkg manager. Specifically, we want to be able to 1) install packages from an arbitrary REQUIRE file and 2) include git URIs in REQUIRE files. Rather than just taking on these features we thought we might do some refactoring to make the API a little cleaner.

For point 1 we currently have a method called `addrequire` that adds the entries from a REQUIRE file to the global REQUIRE file and calls resolve. While the approach seems reasonable I personally don't like the name `addrequire`, so here is my refactoring proposal to address that.

  1. `Pkg.add` should just add a requirement to the global REQUIRE file without doing a resolve. This method should dispatch on a String (package name), URI (remote git uri) and a Path type
    • If the type is a String we check that it is a registered package name and add it to the global REQUIRE file.
    • If the type is a URI we check it and also write it to the global REQUIRE file.
    • if the type is a Path and is a REQUIRE file (`isfile(...)`) add all entries in REQUIRE file, and if the path is a directory (`isdir(...)`) search for a REQUIRE file.
  2. `Pkg.install` should be a wrapper around `Pkg.add` and `Pkg.resolve` and it should also dispatch on the above types and behave in the same way.

Pros:
  • Better utilization of multiple dispatch to help with code & API clarity. Might also help with modularity of `Pkg` in base, but I'd have to dig into the code more.
  • Layered API given that `install` is just a wrapper to `add` and `resolve`
  • Allows installing packages from arbitrary files not just pkg REQUIRE files.
Cons:
  • API change (the existing `Pkg.add` is essentially renamed to `Pkg.install`)
  • Currently would require a URI type and a Path type, which are currently in external packages.

Does this seem reasonable? Do people have other suggestions or ideas?

Thanks,
Rory
Reply | Threaded
Open this post in threaded view
|

Re: Pkg.add refactoring proposal

Yichao Yu
On Tue, Apr 19, 2016 at 12:21 PM, Rory Finnegan <[hidden email]> wrote:

> Hi there,
>
> I'm working at a company that needs to add some features to julia's pkg
> manager. Specifically, we want to be able to 1) install packages from an
> arbitrary REQUIRE file and 2) include git URIs in REQUIRE files. Rather than
> just taking on these features we thought we might do some refactoring to
> make the API a little cleaner.
>
> For point 1 we currently have a method called `addrequire` that adds the
> entries from a REQUIRE file to the global REQUIRE file and calls resolve.
> While the approach seems reasonable I personally don't like the name
> `addrequire`, so here is my refactoring proposal to address that.
>
> `Pkg.add` should just add a requirement to the global REQUIRE file without
> doing a resolve. This method should dispatch on a String (package name), URI
> (remote git uri) and a Path type
>
> If the type is a String we check that it is a registered package name and
> add it to the global REQUIRE file.
> If the type is a URI we check it and also write it to the global REQUIRE
> file.
> if the type is a Path and is a REQUIRE file (`isfile(...)`) add all entries
> in REQUIRE file, and if the path is a directory (`isdir(...)`) search for a
> REQUIRE file.
>
> `Pkg.install` should be a wrapper around `Pkg.add` and `Pkg.resolve` and it
> should also dispatch on the above types and behave in the same way.
>
>
> Pros:
>
> Better utilization of multiple dispatch to help with code & API clarity.
> Might also help with modularity of `Pkg` in base, but I'd have to dig into
> the code more.
> Layered API given that `install` is just a wrapper to `add` and `resolve`
> Allows installing packages from arbitrary files not just pkg REQUIRE files.
>
> Cons:
>
> API change (the existing `Pkg.add` is essentially renamed to `Pkg.install`)
> Currently would require a URI type and a Path type, which are currently in
> external packages.

I think package names and url/filepath are reasonably distinguished so
you don't need to use types to separate them.

Adding a REQUIRE file sounds a little bit arbitrary (it's effectively
a set of packages, maybe with version constraint) so it might make
more sense to allow parsing a REQUIRE file.

>
>
> Does this seem reasonable? Do people have other suggestions or ideas?
>
> Thanks,
> Rory
Reply | Threaded
Open this post in threaded view
|

Re: Pkg.add refactoring proposal

Tony Kelman
In reply to this post by Rory Finnegan
I said this on the PR, but having an API in Pkg that's equivalent to concatenating the contents of a file to the global REQUIRE file seems a bit much. Maybe it could be added to PkgDev, but I'm not understanding the use case for it.


On Tuesday, April 19, 2016 at 9:21:14 AM UTC-7, Rory Finnegan wrote:
Hi there,

I'm working at a company that needs to add some features to julia's pkg manager. Specifically, we want to be able to 1) install packages from an arbitrary REQUIRE file and 2) include git URIs in REQUIRE files. Rather than just taking on these features we thought we might do some refactoring to make the API a little cleaner.

For point 1 we currently have a method called `addrequire` that adds the entries from a REQUIRE file to the global REQUIRE file and calls resolve. While the approach seems reasonable I personally don't like the name `addrequire`, so here is my refactoring proposal to address that.

  1. `Pkg.add` should just add a requirement to the global REQUIRE file without doing a resolve. This method should dispatch on a String (package name), <a href="http://github.com/JuliaWeb/URIParser.jl" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fgithub.com%2FJuliaWeb%2FURIParser.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNEm56plD0nbW7Ta-qoITYnlpugZkQ&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fgithub.com%2FJuliaWeb%2FURIParser.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNEm56plD0nbW7Ta-qoITYnlpugZkQ&#39;;return true;">URI (remote git uri) and a <a href="https://github.com/Rory-Finnegan/Paths.jl" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2FRory-Finnegan%2FPaths.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNHl6-29zsEALfC8qKEB-RGTesRmbA&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2FRory-Finnegan%2FPaths.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNHl6-29zsEALfC8qKEB-RGTesRmbA&#39;;return true;">Path type
    • If the type is a String we check that it is a registered package name and add it to the global REQUIRE file.
    • If the type is a URI we check it and also write it to the global REQUIRE file.
    • if the type is a Path and is a REQUIRE file (`isfile(...)`) add all entries in REQUIRE file, and if the path is a directory (`isdir(...)`) search for a REQUIRE file.
  2. `Pkg.install` should be a wrapper around `Pkg.add` and `Pkg.resolve` and it should also dispatch on the above types and behave in the same way.

Pros:
  • Better utilization of multiple dispatch to help with code & API clarity. Might also help with modularity of `Pkg` in base, but I'd have to dig into the code more.
  • Layered API given that `install` is just a wrapper to `add` and `resolve`
  • Allows installing packages from arbitrary files not just pkg REQUIRE files.
Cons:
  • API change (the existing `Pkg.add` is essentially renamed to `Pkg.install`)
  • Currently would require a URI type and a Path type, which are currently in external packages.

Does this seem reasonable? Do people have other suggestions or ideas?

Thanks,
Rory
Reply | Threaded
Open this post in threaded view
|

Re: Pkg.add refactoring proposal

Rory Finnegan
@Yichao Yu I agree that you could probably make the above refactoring work where URIs and Paths are still just string, and maybe that is the better short term option. On the other hand, I see a lot of benefits to having them be distinct types anyways and this seems like a good place to utilize multiple dispatch to allow more modularity and flexibility.

To clarify, our use case is that we often have julia code that isn't in the form of a package (like a script or notebook), but we still want to distribute a REQUIRE file for it. Right now I usually just include a requirements.jl script that installs the dependencies or just include the dependency list in my instructions on how to run it. I'm open to suggestions if you have a better approach to achieve the same goal.

On Tuesday, 19 April 2016 20:45:41 UTC-4, Tony Kelman wrote:
I said this on the PR, but having an API in Pkg that's equivalent to concatenating the contents of a file to the global REQUIRE file seems a bit much. Maybe it could be added to PkgDev, but I'm not understanding the use case for it.


On Tuesday, April 19, 2016 at 9:21:14 AM UTC-7, Rory Finnegan wrote:
Hi there,

I'm working at a company that needs to add some features to julia's pkg manager. Specifically, we want to be able to 1) install packages from an arbitrary REQUIRE file and 2) include git URIs in REQUIRE files. Rather than just taking on these features we thought we might do some refactoring to make the API a little cleaner.

For point 1 we currently have a method called `addrequire` that adds the entries from a REQUIRE file to the global REQUIRE file and calls resolve. While the approach seems reasonable I personally don't like the name `addrequire`, so here is my refactoring proposal to address that.

  1. `Pkg.add` should just add a requirement to the global REQUIRE file without doing a resolve. This method should dispatch on a String (package name), <a href="http://github.com/JuliaWeb/URIParser.jl" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fgithub.com%2FJuliaWeb%2FURIParser.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNEm56plD0nbW7Ta-qoITYnlpugZkQ&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fgithub.com%2FJuliaWeb%2FURIParser.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNEm56plD0nbW7Ta-qoITYnlpugZkQ&#39;;return true;">URI (remote git uri) and a <a href="https://github.com/Rory-Finnegan/Paths.jl" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2FRory-Finnegan%2FPaths.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNHl6-29zsEALfC8qKEB-RGTesRmbA&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2FRory-Finnegan%2FPaths.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNHl6-29zsEALfC8qKEB-RGTesRmbA&#39;;return true;">Path type
    • If the type is a String we check that it is a registered package name and add it to the global REQUIRE file.
    • If the type is a URI we check it and also write it to the global REQUIRE file.
    • if the type is a Path and is a REQUIRE file (`isfile(...)`) add all entries in REQUIRE file, and if the path is a directory (`isdir(...)`) search for a REQUIRE file.
  2. `Pkg.install` should be a wrapper around `Pkg.add` and `Pkg.resolve` and it should also dispatch on the above types and behave in the same way.

Pros:
  • Better utilization of multiple dispatch to help with code & API clarity. Might also help with modularity of `Pkg` in base, but I'd have to dig into the code more.
  • Layered API given that `install` is just a wrapper to `add` and `resolve`
  • Allows installing packages from arbitrary files not just pkg REQUIRE files.
Cons:
  • API change (the existing `Pkg.add` is essentially renamed to `Pkg.install`)
  • Currently would require a URI type and a Path type, which are currently in external packages.

Does this seem reasonable? Do people have other suggestions or ideas?

Thanks,
Rory
Reply | Threaded
Open this post in threaded view
|

Re: Pkg.add refactoring proposal

Jeffrey Sarnoff
Changing the use/syntax/scope of Julia's REQUIRE files to meet a specific need seems to be a `sticky` approach that may make future work not tidy.  

One way may be to continue using your requirements.jl script but put in PKG.jl/deps/ alongside a simple build.jl file that incorporates or calls it (as appropriate).  That way, your unpackaged dependencies should be fetched and placed/processed as you need when the PKG is add_ed.  And, whenever there is an upgrade to one of the unpackaged dependencies, running Pkg.bulid("PKG") will refetch and reput/reprocess all of them. I don't know what is in the requirements.jl file .. if it is not too much, the contents may better live in the build.jl file directly. Take a look at BinDeps.jl for more possibilities (remember to put BinDeps in the usual REQUIRE file if you end up using it).



On Tuesday, April 19, 2016 at 9:34:33 PM UTC-4, Rory Finnegan wrote:
@Yichao Yu I agree that you could probably make the above refactoring work where URIs and Paths are still just string, and maybe that is the better short term option. On the other hand, I see a lot of benefits to having them be distinct types anyways and this seems like a good place to utilize multiple dispatch to allow more modularity and flexibility.

To clarify, our use case is that we often have julia code that isn't in the form of a package (like a script or notebook), but we still want to distribute a REQUIRE file for it. Right now I usually just include a requirements.jl script that installs the dependencies or just include the dependency list in my instructions on how to run it. I'm open to suggestions if you have a better approach to achieve the same goal.

On Tuesday, 19 April 2016 20:45:41 UTC-4, Tony Kelman wrote:
I said this on the PR, but having an API in Pkg that's equivalent to concatenating the contents of a file to the global REQUIRE file seems a bit much. Maybe it could be added to PkgDev, but I'm not understanding the use case for it.


On Tuesday, April 19, 2016 at 9:21:14 AM UTC-7, Rory Finnegan wrote:
Hi there,

I'm working at a company that needs to add some features to julia's pkg manager. Specifically, we want to be able to 1) install packages from an arbitrary REQUIRE file and 2) include git URIs in REQUIRE files. Rather than just taking on these features we thought we might do some refactoring to make the API a little cleaner.

For point 1 we currently have a method called `addrequire` that adds the entries from a REQUIRE file to the global REQUIRE file and calls resolve. While the approach seems reasonable I personally don't like the name `addrequire`, so here is my refactoring proposal to address that.

  1. `Pkg.add` should just add a requirement to the global REQUIRE file without doing a resolve. This method should dispatch on a String (package name), <a href="http://github.com/JuliaWeb/URIParser.jl" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fgithub.com%2FJuliaWeb%2FURIParser.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNEm56plD0nbW7Ta-qoITYnlpugZkQ&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fgithub.com%2FJuliaWeb%2FURIParser.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNEm56plD0nbW7Ta-qoITYnlpugZkQ&#39;;return true;">URI (remote git uri) and a <a href="https://github.com/Rory-Finnegan/Paths.jl" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2FRory-Finnegan%2FPaths.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNHl6-29zsEALfC8qKEB-RGTesRmbA&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2FRory-Finnegan%2FPaths.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNHl6-29zsEALfC8qKEB-RGTesRmbA&#39;;return true;">Path type
    • If the type is a String we check that it is a registered package name and add it to the global REQUIRE file.
    • If the type is a URI we check it and also write it to the global REQUIRE file.
    • if the type is a Path and is a REQUIRE file (`isfile(...)`) add all entries in REQUIRE file, and if the path is a directory (`isdir(...)`) search for a REQUIRE file.
  2. `Pkg.install` should be a wrapper around `Pkg.add` and `Pkg.resolve` and it should also dispatch on the above types and behave in the same way.

Pros:
  • Better utilization of multiple dispatch to help with code & API clarity. Might also help with modularity of `Pkg` in base, but I'd have to dig into the code more.
  • Layered API given that `install` is just a wrapper to `add` and `resolve`
  • Allows installing packages from arbitrary files not just pkg REQUIRE files.
Cons:
  • API change (the existing `Pkg.add` is essentially renamed to `Pkg.install`)
  • Currently would require a URI type and a Path type, which are currently in external packages.

Does this seem reasonable? Do people have other suggestions or ideas?

Thanks,
Rory
Reply | Threaded
Open this post in threaded view
|

Re: Pkg.add refactoring proposal

Rory Finnegan
@Jeffrey Sarnoff I'm not distributing a pkg, just a single script or notebook. Making an entire package for one script and a REQUIRE file seems a bit much.

On Wednesday, 20 April 2016 00:25:03 UTC-4, Jeffrey Sarnoff wrote:
Changing the use/syntax/scope of Julia's REQUIRE files to meet a specific need seems to be a `sticky` approach that may make future work not tidy.  

One way may be to continue using your requirements.jl script but put in PKG.jl/deps/ alongside a simple build.jl file that incorporates or calls it (as appropriate).  That way, your unpackaged dependencies should be fetched and placed/processed as you need when the PKG is add_ed.  And, whenever there is an upgrade to one of the unpackaged dependencies, running Pkg.bulid("PKG") will refetch and reput/reprocess all of them. I don't know what is in the requirements.jl file .. if it is not too much, the contents may better live in the build.jl file directly. Take a look at <a href="https://github.com/JuliaLang/BinDeps.jl" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2FJuliaLang%2FBinDeps.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNGCvsoj9ZasX0OgrauoF6dUHROkeQ&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2FJuliaLang%2FBinDeps.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNGCvsoj9ZasX0OgrauoF6dUHROkeQ&#39;;return true;">BinDeps.jl for more possibilities (remember to put BinDeps in the usual REQUIRE file if you end up using it).



On Tuesday, April 19, 2016 at 9:34:33 PM UTC-4, Rory Finnegan wrote:
@Yichao Yu I agree that you could probably make the above refactoring work where URIs and Paths are still just string, and maybe that is the better short term option. On the other hand, I see a lot of benefits to having them be distinct types anyways and this seems like a good place to utilize multiple dispatch to allow more modularity and flexibility.

To clarify, our use case is that we often have julia code that isn't in the form of a package (like a script or notebook), but we still want to distribute a REQUIRE file for it. Right now I usually just include a requirements.jl script that installs the dependencies or just include the dependency list in my instructions on how to run it. I'm open to suggestions if you have a better approach to achieve the same goal.

On Tuesday, 19 April 2016 20:45:41 UTC-4, Tony Kelman wrote:
I said this on the PR, but having an API in Pkg that's equivalent to concatenating the contents of a file to the global REQUIRE file seems a bit much. Maybe it could be added to PkgDev, but I'm not understanding the use case for it.


On Tuesday, April 19, 2016 at 9:21:14 AM UTC-7, Rory Finnegan wrote:
Hi there,

I'm working at a company that needs to add some features to julia's pkg manager. Specifically, we want to be able to 1) install packages from an arbitrary REQUIRE file and 2) include git URIs in REQUIRE files. Rather than just taking on these features we thought we might do some refactoring to make the API a little cleaner.

For point 1 we currently have a method called `addrequire` that adds the entries from a REQUIRE file to the global REQUIRE file and calls resolve. While the approach seems reasonable I personally don't like the name `addrequire`, so here is my refactoring proposal to address that.

  1. `Pkg.add` should just add a requirement to the global REQUIRE file without doing a resolve. This method should dispatch on a String (package name), <a href="http://github.com/JuliaWeb/URIParser.jl" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fgithub.com%2FJuliaWeb%2FURIParser.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNEm56plD0nbW7Ta-qoITYnlpugZkQ&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fgithub.com%2FJuliaWeb%2FURIParser.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNEm56plD0nbW7Ta-qoITYnlpugZkQ&#39;;return true;">URI (remote git uri) and a <a href="https://github.com/Rory-Finnegan/Paths.jl" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2FRory-Finnegan%2FPaths.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNHl6-29zsEALfC8qKEB-RGTesRmbA&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2FRory-Finnegan%2FPaths.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNHl6-29zsEALfC8qKEB-RGTesRmbA&#39;;return true;">Path type
    • If the type is a String we check that it is a registered package name and add it to the global REQUIRE file.
    • If the type is a URI we check it and also write it to the global REQUIRE file.
    • if the type is a Path and is a REQUIRE file (`isfile(...)`) add all entries in REQUIRE file, and if the path is a directory (`isdir(...)`) search for a REQUIRE file.
  2. `Pkg.install` should be a wrapper around `Pkg.add` and `Pkg.resolve` and it should also dispatch on the above types and behave in the same way.

Pros:
  • Better utilization of multiple dispatch to help with code & API clarity. Might also help with modularity of `Pkg` in base, but I'd have to dig into the code more.
  • Layered API given that `install` is just a wrapper to `add` and `resolve`
  • Allows installing packages from arbitrary files not just pkg REQUIRE files.
Cons:
  • API change (the existing `Pkg.add` is essentially renamed to `Pkg.install`)
  • Currently would require a URI type and a Path type, which are currently in external packages.

Does this seem reasonable? Do people have other suggestions or ideas?

Thanks,
Rory
Reply | Threaded
Open this post in threaded view
|

Re: Pkg.add refactoring proposal

Tom Breloff
Rory: have you had a chance to review https://github.com/tshort/Maker.jl?  It seems like this might be the right sort of application of that package.  (disclaimer: I haven't used it yet)

On Wed, Apr 20, 2016 at 9:40 AM, Rory Finnegan <[hidden email]> wrote:
@Jeffrey Sarnoff I'm not distributing a pkg, just a single script or notebook. Making an entire package for one script and a REQUIRE file seems a bit much.


On Wednesday, 20 April 2016 00:25:03 UTC-4, Jeffrey Sarnoff wrote:
Changing the use/syntax/scope of Julia's REQUIRE files to meet a specific need seems to be a `sticky` approach that may make future work not tidy.  

One way may be to continue using your requirements.jl script but put in PKG.jl/deps/ alongside a simple build.jl file that incorporates or calls it (as appropriate).  That way, your unpackaged dependencies should be fetched and placed/processed as you need when the PKG is add_ed.  And, whenever there is an upgrade to one of the unpackaged dependencies, running Pkg.bulid("PKG") will refetch and reput/reprocess all of them. I don't know what is in the requirements.jl file .. if it is not too much, the contents may better live in the build.jl file directly. Take a look at BinDeps.jl for more possibilities (remember to put BinDeps in the usual REQUIRE file if you end up using it).



On Tuesday, April 19, 2016 at 9:34:33 PM UTC-4, Rory Finnegan wrote:
@Yichao Yu I agree that you could probably make the above refactoring work where URIs and Paths are still just string, and maybe that is the better short term option. On the other hand, I see a lot of benefits to having them be distinct types anyways and this seems like a good place to utilize multiple dispatch to allow more modularity and flexibility.

To clarify, our use case is that we often have julia code that isn't in the form of a package (like a script or notebook), but we still want to distribute a REQUIRE file for it. Right now I usually just include a requirements.jl script that installs the dependencies or just include the dependency list in my instructions on how to run it. I'm open to suggestions if you have a better approach to achieve the same goal.

On Tuesday, 19 April 2016 20:45:41 UTC-4, Tony Kelman wrote:
I said this on the PR, but having an API in Pkg that's equivalent to concatenating the contents of a file to the global REQUIRE file seems a bit much. Maybe it could be added to PkgDev, but I'm not understanding the use case for it.


On Tuesday, April 19, 2016 at 9:21:14 AM UTC-7, Rory Finnegan wrote:
Hi there,

I'm working at a company that needs to add some features to julia's pkg manager. Specifically, we want to be able to 1) install packages from an arbitrary REQUIRE file and 2) include git URIs in REQUIRE files. Rather than just taking on these features we thought we might do some refactoring to make the API a little cleaner.

For point 1 we currently have a method called `addrequire` that adds the entries from a REQUIRE file to the global REQUIRE file and calls resolve. While the approach seems reasonable I personally don't like the name `addrequire`, so here is my refactoring proposal to address that.

  1. `Pkg.add` should just add a requirement to the global REQUIRE file without doing a resolve. This method should dispatch on a String (package name), URI (remote git uri) and a Path type
    • If the type is a String we check that it is a registered package name and add it to the global REQUIRE file.
    • If the type is a URI we check it and also write it to the global REQUIRE file.
    • if the type is a Path and is a REQUIRE file (`isfile(...)`) add all entries in REQUIRE file, and if the path is a directory (`isdir(...)`) search for a REQUIRE file.
  2. `Pkg.install` should be a wrapper around `Pkg.add` and `Pkg.resolve` and it should also dispatch on the above types and behave in the same way.

Pros:
  • Better utilization of multiple dispatch to help with code & API clarity. Might also help with modularity of `Pkg` in base, but I'd have to dig into the code more.
  • Layered API given that `install` is just a wrapper to `add` and `resolve`
  • Allows installing packages from arbitrary files not just pkg REQUIRE files.
Cons:
  • API change (the existing `Pkg.add` is essentially renamed to `Pkg.install`)
  • Currently would require a URI type and a Path type, which are currently in external packages.

Does this seem reasonable? Do people have other suggestions or ideas?

Thanks,
Rory

Reply | Threaded
Open this post in threaded view
|

Re: Pkg.add refactoring proposal

Jeffrey Sarnoff
In reply to this post by Rory Finnegan
Making a package that allows you to distribute any single script or notebook that you may need to distribute, assuming this may change with time, might work well for you -- alternatively, if this is about a couple of notebooks, take a look at NBInclude.jl:

"NBInclude is a package for the Julia language which allows you to include and execute IJulia (Julia-language Jupyter) notebook files just as you would include an ordinary Julia file. "


On Wednesday, April 20, 2016 at 9:40:38 AM UTC-4, Rory Finnegan wrote:
@Jeffrey Sarnoff I'm not distributing a pkg, just a single script or notebook. Making an entire package for one script and a REQUIRE file seems a bit much.

On Wednesday, 20 April 2016 00:25:03 UTC-4, Jeffrey Sarnoff wrote:
Changing the use/syntax/scope of Julia's REQUIRE files to meet a specific need seems to be a `sticky` approach that may make future work not tidy.  

One way may be to continue using your requirements.jl script but put in PKG.jl/deps/ alongside a simple build.jl file that incorporates or calls it (as appropriate).  That way, your unpackaged dependencies should be fetched and placed/processed as you need when the PKG is add_ed.  And, whenever there is an upgrade to one of the unpackaged dependencies, running Pkg.bulid("PKG") will refetch and reput/reprocess all of them. I don't know what is in the requirements.jl file .. if it is not too much, the contents may better live in the build.jl file directly. Take a look at <a href="https://github.com/JuliaLang/BinDeps.jl" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2FJuliaLang%2FBinDeps.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNGCvsoj9ZasX0OgrauoF6dUHROkeQ&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2FJuliaLang%2FBinDeps.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNGCvsoj9ZasX0OgrauoF6dUHROkeQ&#39;;return true;">BinDeps.jl for more possibilities (remember to put BinDeps in the usual REQUIRE file if you end up using it).



On Tuesday, April 19, 2016 at 9:34:33 PM UTC-4, Rory Finnegan wrote:
@Yichao Yu I agree that you could probably make the above refactoring work where URIs and Paths are still just string, and maybe that is the better short term option. On the other hand, I see a lot of benefits to having them be distinct types anyways and this seems like a good place to utilize multiple dispatch to allow more modularity and flexibility.

To clarify, our use case is that we often have julia code that isn't in the form of a package (like a script or notebook), but we still want to distribute a REQUIRE file for it. Right now I usually just include a requirements.jl script that installs the dependencies or just include the dependency list in my instructions on how to run it. I'm open to suggestions if you have a better approach to achieve the same goal.

On Tuesday, 19 April 2016 20:45:41 UTC-4, Tony Kelman wrote:
I said this on the PR, but having an API in Pkg that's equivalent to concatenating the contents of a file to the global REQUIRE file seems a bit much. Maybe it could be added to PkgDev, but I'm not understanding the use case for it.


On Tuesday, April 19, 2016 at 9:21:14 AM UTC-7, Rory Finnegan wrote:
Hi there,

I'm working at a company that needs to add some features to julia's pkg manager. Specifically, we want to be able to 1) install packages from an arbitrary REQUIRE file and 2) include git URIs in REQUIRE files. Rather than just taking on these features we thought we might do some refactoring to make the API a little cleaner.

For point 1 we currently have a method called `addrequire` that adds the entries from a REQUIRE file to the global REQUIRE file and calls resolve. While the approach seems reasonable I personally don't like the name `addrequire`, so here is my refactoring proposal to address that.

  1. `Pkg.add` should just add a requirement to the global REQUIRE file without doing a resolve. This method should dispatch on a String (package name), <a href="http://github.com/JuliaWeb/URIParser.jl" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fgithub.com%2FJuliaWeb%2FURIParser.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNEm56plD0nbW7Ta-qoITYnlpugZkQ&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\75http%3A%2F%2Fgithub.com%2FJuliaWeb%2FURIParser.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNEm56plD0nbW7Ta-qoITYnlpugZkQ&#39;;return true;">URI (remote git uri) and a <a href="https://github.com/Rory-Finnegan/Paths.jl" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2FRory-Finnegan%2FPaths.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNHl6-29zsEALfC8qKEB-RGTesRmbA&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\75https%3A%2F%2Fgithub.com%2FRory-Finnegan%2FPaths.jl\46sa\75D\46sntz\0751\46usg\75AFQjCNHl6-29zsEALfC8qKEB-RGTesRmbA&#39;;return true;">Path type
    • If the type is a String we check that it is a registered package name and add it to the global REQUIRE file.
    • If the type is a URI we check it and also write it to the global REQUIRE file.
    • if the type is a Path and is a REQUIRE file (`isfile(...)`) add all entries in REQUIRE file, and if the path is a directory (`isdir(...)`) search for a REQUIRE file.
  2. `Pkg.install` should be a wrapper around `Pkg.add` and `Pkg.resolve` and it should also dispatch on the above types and behave in the same way.

Pros:
  • Better utilization of multiple dispatch to help with code & API clarity. Might also help with modularity of `Pkg` in base, but I'd have to dig into the code more.
  • Layered API given that `install` is just a wrapper to `add` and `resolve`
  • Allows installing packages from arbitrary files not just pkg REQUIRE files.
Cons:
  • API change (the existing `Pkg.add` is essentially renamed to `Pkg.install`)
  • Currently would require a URI type and a Path type, which are currently in external packages.

Does this seem reasonable? Do people have other suggestions or ideas?

Thanks,
Rory
Reply | Threaded
Open this post in threaded view
|

Re: Pkg.add refactoring proposal

wildart
Rory, I think the issue is much bigger than modification of the package manager installation routine. You wish a project dependency management, but julia does not provide one. I could see a  simple solution - reorder package loading to prioritize LOAD_PATH over Pkg.dir(). As soon as it's changed, LOAD_PATH can be injected with some local directory in your project that would hold all dependencies. So, then you clone or copy dependencies and local project is ready to run. All these steps can be automated and included in the julia's package manager.

On Wednesday, April 20, 2016 at 9:50:59 AM UTC-4, Jeffrey Sarnoff wrote:
Making a package that allows you to distribute any single script or notebook that you may need to distribute, assuming this may change with time, might work well for you -- alternatively, if this is about a couple of notebooks, take a look at <a href="https://github.com/stevengj/NBInclude.jl" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fstevengj%2FNBInclude.jl\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNG61ActwBodcopx8lJc5NbQj-aWTQ&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fstevengj%2FNBInclude.jl\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNG61ActwBodcopx8lJc5NbQj-aWTQ&#39;;return true;">NBInclude.jl:

"NBInclude is a package for the <a href="http://julialang.org/" style="color:rgb(64,120,192);background-color:transparent" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fjulialang.org%2F\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFDhjHIhllRBZ-d-bLtw3PuY5T3Aw&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fjulialang.org%2F\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFDhjHIhllRBZ-d-bLtw3PuY5T3Aw&#39;;return true;">Julia language which allows you to include and execute <a href="https://github.com/JuliaLang/IJulia.jl" style="color:rgb(64,120,192);background-color:transparent" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FJuliaLang%2FIJulia.jl\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEhaU5ATGEUZRKeaurpm4gDvf3oFg&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FJuliaLang%2FIJulia.jl\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEhaU5ATGEUZRKeaurpm4gDvf3oFg&#39;;return true;">IJulia (Julia-language <a href="https://jupyter.org/" style="color:rgb(64,120,192);background-color:transparent" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fjupyter.org%2F\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHJdO-sPt33HA58sqPCjv3XvAhLEA&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fjupyter.org%2F\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHJdO-sPt33HA58sqPCjv3XvAhLEA&#39;;return true;">Jupyter) notebook files just as you would include an ordinary Julia file. "


On Wednesday, April 20, 2016 at 9:40:38 AM UTC-4, Rory Finnegan wrote:
@Jeffrey Sarnoff I'm not distributing a pkg, just a single script or notebook. Making an entire package for one script and a REQUIRE file seems a bit much.

On Wednesday, 20 April 2016 00:25:03 UTC-4, Jeffrey Sarnoff wrote:
Changing the use/syntax/scope of Julia's REQUIRE files to meet a specific need seems to be a `sticky` approach that may make future work not tidy.  

One way may be to continue using your requirements.jl script but put in PKG.jl/deps/ alongside a simple build.jl file that incorporates or calls it (as appropriate).  That way, your unpackaged dependencies should be fetched and placed/processed as you need when the PKG is add_ed.  And, whenever there is an upgrade to one of the unpackaged dependencies, running Pkg.bulid("PKG") will refetch and reput/reprocess all of them. I don't know what is in the requirements.jl file .. if it is not too much, the contents may better live in the build.jl file directly. Take a look at <a href="https://github.com/JuliaLang/BinDeps.jl" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FJuliaLang%2FBinDeps.jl\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGCvsoj9ZasX0OgrauoF6dUHROkeQ&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FJuliaLang%2FBinDeps.jl\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGCvsoj9ZasX0OgrauoF6dUHROkeQ&#39;;return true;">BinDeps.jl for more possibilities (remember to put BinDeps in the usual REQUIRE file if you end up using it).



On Tuesday, April 19, 2016 at 9:34:33 PM UTC-4, Rory Finnegan wrote:
@Yichao Yu I agree that you could probably make the above refactoring work where URIs and Paths are still just string, and maybe that is the better short term option. On the other hand, I see a lot of benefits to having them be distinct types anyways and this seems like a good place to utilize multiple dispatch to allow more modularity and flexibility.

To clarify, our use case is that we often have julia code that isn't in the form of a package (like a script or notebook), but we still want to distribute a REQUIRE file for it. Right now I usually just include a requirements.jl script that installs the dependencies or just include the dependency list in my instructions on how to run it. I'm open to suggestions if you have a better approach to achieve the same goal.

On Tuesday, 19 April 2016 20:45:41 UTC-4, Tony Kelman wrote:
I said this on the PR, but having an API in Pkg that's equivalent to concatenating the contents of a file to the global REQUIRE file seems a bit much. Maybe it could be added to PkgDev, but I'm not understanding the use case for it.


On Tuesday, April 19, 2016 at 9:21:14 AM UTC-7, Rory Finnegan wrote:
Hi there,

I'm working at a company that needs to add some features to julia's pkg manager. Specifically, we want to be able to 1) install packages from an arbitrary REQUIRE file and 2) include git URIs in REQUIRE files. Rather than just taking on these features we thought we might do some refactoring to make the API a little cleaner.

For point 1 we currently have a method called `addrequire` that adds the entries from a REQUIRE file to the global REQUIRE file and calls resolve. While the approach seems reasonable I personally don't like the name `addrequire`, so here is my refactoring proposal to address that.

  1. `Pkg.add` should just add a requirement to the global REQUIRE file without doing a resolve. This method should dispatch on a String (package name), <a href="http://github.com/JuliaWeb/URIParser.jl" rel="nofollow" target="_blank" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fgithub.com%2FJuliaWeb%2FURIParser.jl\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEm56plD0nbW7Ta-qoITYnlpugZkQ&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fgithub.com%2FJuliaWeb%2FURIParser.jl\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEm56plD0nbW7Ta-qoITYnlpugZkQ&#39;;return true;">URI (remote git uri) and a <a href="https://github.com/Rory-Finnegan/Paths.jl" rel="nofollow" target="_blank" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FRory-Finnegan%2FPaths.jl\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHl6-29zsEALfC8qKEB-RGTesRmbA&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FRory-Finnegan%2FPaths.jl\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHl6-29zsEALfC8qKEB-RGTesRmbA&#39;;return true;">Path type
    • If the type is a String we check that it is a registered package name and add it to the global REQUIRE file.
    • If the type is a URI we check it and also write it to the global REQUIRE file.
    • if the type is a Path and is a REQUIRE file (`isfile(...)`) add all entries in REQUIRE file, and if the path is a directory (`isdir(...)`) search for a REQUIRE file.
  2. `Pkg.install` should be a wrapper around `Pkg.add` and `Pkg.resolve` and it should also dispatch on the above types and behave in the same way.

Pros:
  • Better utilization of multiple dispatch to help with code & API clarity. Might also help with modularity of `Pkg` in base, but I'd have to dig into the code more.
  • Layered API given that `install` is just a wrapper to `add` and `resolve`
  • Allows installing packages from arbitrary files not just pkg REQUIRE files.
Cons:
  • API change (the existing `Pkg.add` is essentially renamed to `Pkg.install`)
  • Currently would require a URI type and a Path type, which are currently in external packages.

Does this seem reasonable? Do people have other suggestions or ideas?

Thanks,
Rory
Reply | Threaded
Open this post in threaded view
|

Re: Pkg.add refactoring proposal

Chris Foster
Rory - did you check out DeclarativePackages.jl?  We're using this for
managing a subset of dependencies outside the main METADATA.jl
(including prerelease testing of unreleased packages, specified only
with a git url).  If you care about reproducible builds it's also
pretty great!


On Mon, May 2, 2016 at 1:20 AM,  <[hidden email]> wrote:

> Rory, I think the issue is much bigger than modification of the package
> manager installation routine. You wish a project dependency management, but
> julia does not provide one. I could see a  simple solution - reorder package
> loading to prioritize LOAD_PATH over Pkg.dir(). As soon as it's changed,
> LOAD_PATH can be injected with some local directory in your project that
> would hold all dependencies. So, then you clone or copy dependencies and
> local project is ready to run. All these steps can be automated and included
> in the julia's package manager.
>
> On Wednesday, April 20, 2016 at 9:50:59 AM UTC-4, Jeffrey Sarnoff wrote:
>>
>> Making a package that allows you to distribute any single script or
>> notebook that you may need to distribute, assuming this may change with
>> time, might work well for you -- alternatively, if this is about a couple of
>> notebooks, take a look at NBInclude.jl:
>>
>> "NBInclude is a package for the Julia language which allows you to include
>> and execute IJulia (Julia-language Jupyter) notebook files just as you would
>> include an ordinary Julia file. "
>>
>>
>> On Wednesday, April 20, 2016 at 9:40:38 AM UTC-4, Rory Finnegan wrote:
>>>
>>> @Jeffrey Sarnoff I'm not distributing a pkg, just a single script or
>>> notebook. Making an entire package for one script and a REQUIRE file seems a
>>> bit much.
>>>
>>> On Wednesday, 20 April 2016 00:25:03 UTC-4, Jeffrey Sarnoff wrote:
>>>>
>>>> Changing the use/syntax/scope of Julia's REQUIRE files to meet a
>>>> specific need seems to be a `sticky` approach that may make future work not
>>>> tidy.
>>>>
>>>> One way may be to continue using your requirements.jl script but put in
>>>> PKG.jl/deps/ alongside a simple build.jl file that incorporates or calls it
>>>> (as appropriate).  That way, your unpackaged dependencies should be fetched
>>>> and placed/processed as you need when the PKG is add_ed.  And, whenever
>>>> there is an upgrade to one of the unpackaged dependencies, running
>>>> Pkg.bulid("PKG") will refetch and reput/reprocess all of them. I don't know
>>>> what is in the requirements.jl file .. if it is not too much, the contents
>>>> may better live in the build.jl file directly. Take a look at BinDeps.jl for
>>>> more possibilities (remember to put BinDeps in the usual REQUIRE file if you
>>>> end up using it).
>>>>
>>>>
>>>>
>>>> On Tuesday, April 19, 2016 at 9:34:33 PM UTC-4, Rory Finnegan wrote:
>>>>>
>>>>> @Yichao Yu I agree that you could probably make the above refactoring
>>>>> work where URIs and Paths are still just string, and maybe that is the
>>>>> better short term option. On the other hand, I see a lot of benefits to
>>>>> having them be distinct types anyways and this seems like a good place to
>>>>> utilize multiple dispatch to allow more modularity and flexibility.
>>>>>
>>>>> To clarify, our use case is that we often have julia code that isn't in
>>>>> the form of a package (like a script or notebook), but we still want to
>>>>> distribute a REQUIRE file for it. Right now I usually just include a
>>>>> requirements.jl script that installs the dependencies or just include the
>>>>> dependency list in my instructions on how to run it. I'm open to suggestions
>>>>> if you have a better approach to achieve the same goal.
>>>>>
>>>>> On Tuesday, 19 April 2016 20:45:41 UTC-4, Tony Kelman wrote:
>>>>>>
>>>>>> I said this on the PR, but having an API in Pkg that's equivalent to
>>>>>> concatenating the contents of a file to the global REQUIRE file seems a bit
>>>>>> much. Maybe it could be added to PkgDev, but I'm not understanding the use
>>>>>> case for it.
>>>>>>
>>>>>>
>>>>>> On Tuesday, April 19, 2016 at 9:21:14 AM UTC-7, Rory Finnegan wrote:
>>>>>>>
>>>>>>> Hi there,
>>>>>>>
>>>>>>> I'm working at a company that needs to add some features to julia's
>>>>>>> pkg manager. Specifically, we want to be able to 1) install packages from an
>>>>>>> arbitrary REQUIRE file and 2) include git URIs in REQUIRE files. Rather than
>>>>>>> just taking on these features we thought we might do some refactoring to
>>>>>>> make the API a little cleaner.
>>>>>>>
>>>>>>> For point 1 we currently have a method called `addrequire` that adds
>>>>>>> the entries from a REQUIRE file to the global REQUIRE file and calls
>>>>>>> resolve. While the approach seems reasonable I personally don't like the
>>>>>>> name `addrequire`, so here is my refactoring proposal to address that.
>>>>>>>
>>>>>>> `Pkg.add` should just add a requirement to the global REQUIRE file
>>>>>>> without doing a resolve. This method should dispatch on a String (package
>>>>>>> name), URI (remote git uri) and a Path type
>>>>>>>
>>>>>>> If the type is a String we check that it is a registered package name
>>>>>>> and add it to the global REQUIRE file.
>>>>>>> If the type is a URI we check it and also write it to the global
>>>>>>> REQUIRE file.
>>>>>>> if the type is a Path and is a REQUIRE file (`isfile(...)`) add all
>>>>>>> entries in REQUIRE file, and if the path is a directory (`isdir(...)`)
>>>>>>> search for a REQUIRE file.
>>>>>>>
>>>>>>> `Pkg.install` should be a wrapper around `Pkg.add` and `Pkg.resolve`
>>>>>>> and it should also dispatch on the above types and behave in the same way.
>>>>>>>
>>>>>>>
>>>>>>> Pros:
>>>>>>>
>>>>>>> Better utilization of multiple dispatch to help with code & API
>>>>>>> clarity. Might also help with modularity of `Pkg` in base, but I'd have to
>>>>>>> dig into the code more.
>>>>>>> Layered API given that `install` is just a wrapper to `add` and
>>>>>>> `resolve`
>>>>>>> Allows installing packages from arbitrary files not just pkg REQUIRE
>>>>>>> files.
>>>>>>>
>>>>>>> Cons:
>>>>>>>
>>>>>>> API change (the existing `Pkg.add` is essentially renamed to
>>>>>>> `Pkg.install`)
>>>>>>> Currently would require a URI type and a Path type, which are
>>>>>>> currently in external packages.
>>>>>>>
>>>>>>>
>>>>>>> Does this seem reasonable? Do people have other suggestions or ideas?
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Rory