-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WiP: URI Rework #1665
WiP: URI Rework #1665
Conversation
The underlying work to provide implementations of these methods has not been done yet pending discussion, so this will break the build. This also adds Destroy() as described in fyne-io#1509, though again no implementation is defined yet. This also adds detailed comments to the members of the URI interface, to make it clear what is expected of URI implementations.
Would like some input from @andydotxyz / @stuartmscott relating to the proposed changes before I do the legwork to implement. See commends in the diff. |
For the record, I agree with Stuart's changes, but am waiting to put more commits into this until everybody is agreed on the relevant proposal. |
This will be immediately reverted, but if we decide to revive it for some reason, it might be a good starting point. I started writing this and then realized Go already has an RFC3986 implementation here: https://golang.org/pkg/net/url/ I plan to use that unless there is some reason to build out or own instead.
This reverts commit adf04ad.
In retrospect, there is a lot of redundancy In the prose of the given implementation. I will do a second pass to tidy it up at some point.
Note that I have veered much more towards @toaster 's (Tilo) proposal than I had originally. My change of heart is documented in the relevant proposal here: https://github.com/fyne-io/fyne/wiki/Proposal%3A-The-Fyne-URI-Philosophy I have decided not to implement URINotListable on the basis that URIOperationImpossible already encompasses it's purpose, and additionally I want to encourage people to use Listable() rather than just trying to List() and then checking the error. I decided to move List and Listable() into the Repository interface, though developers can always throw URIOperatioNotSupported if they are impossible to implement. I could be convinced to move them into their own ListableRepository interface to be optionally registered, but to keep them together (since you cannot have one without the other). This was discussed a little bit, but I am on the fence. Since I decided to go with more of Tilo's approach, I did not add Move() or Duplicate(). If folks have opinions on using these names versus Rename() and Copy(), please add them on the PR.
I have sketched out more or less what my current thinking is on the API in a87a205 and also wrote a commit message with some more thoughts. If people have objections, now is the time to raise them. We are getting down to the wire on 2.X. I have done my very best to balance what I believe will be a good API design, what will be backwards compatible with the existing 1.4.X API, and what we have discussed in previous meetings and in the proposal. One thing I would like explicit comments on is whether folks feel we should move |
Specifically paging @andydotxyz, @toaster, @stuartmscott, and @AlbinoGeek w.r.t the above comment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I'm currently having a hard time (mentally) putting together an implementation for the Repository, after reviewing the code I feel it should be straight-forward to use. However, an example would go a long way in helping that.
I may have missed this somewhere, should file://
scheme be implemented as a Repository, to make sure it conforms with the interface, etc? (this would also be a great way to tell if any major / important features were missing from the API.)
That would serve as a great example. Does it belong in another PR or this one?
Overall I like the direction and can't wait to see what others think too.
// the appropriate repository. | ||
// | ||
// NOTE: functions in a particular repository can assume they will only ever be | ||
// used on URIs which match the scheme that they have been registered to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This wording (to me, when I read it) implied an almost one-to-one relationship of Repository to scheme, where a Repository may be capable of handling multiple schemes. Cases would even exist where multiple repositories support the same scheme.
// is supported by the underlying implementation, but which violates some | ||
// internal constraints of that particular repository implementation. For | ||
// example, creating an un-representable state might cause this error to occur. | ||
const URIOperationImpossible uriOperationImpossible = uriOperationImpossible("The requested URI operation is not possible.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be worded in a way where it more specifically refers to the operation not being possible with that URI, or is this error also used in contexts outsides of an error specific to one repository implementation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks really solid.
A few changes requested and thoughts inline but I think this fulfils the requirements.
Some other thoughts back on the URI philosophy document so it's consistent.
// to a particular URI scheme. | ||
// | ||
// Since 2.0.0 | ||
Init() func() error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about including Init
to be run during register - if we are supporting a single Repository
backing multiple schemes then this could be called multiple times, which the name does not imply.
What is this needed for that cannot be expected of the implementation before calling Register
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am also not sure this needs to be included. I envisioned the initialization going the other way, where the developer initializes a repository, most likely by importing a third party library, which runs its func init()
, which registers itself with the storage API (like when importing "image/png")
// error if it does. | ||
// | ||
// Since 2.0.0 | ||
func RegisterRepository(scheme string, repository Repository) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that Repository
is the "main" interface, I would suggest Register(string, Repository)
so it is more clearly differentiated from the optional registrations above.
// with a URIOperationNotSupported error. | ||
// | ||
// Since 2.0.0 | ||
func Listable(u fyne.URI) (bool, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Listable
feels almost an assertion, would CanList
be OK? It feels less ambiguous.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or IsListable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That crossed my mind to, though generally we prefer to drop "Get" and "Is" prefixes.
package storage | ||
|
||
// Declare conformance with Error interface | ||
var _ error = URIOperationImpossible |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sure it would be OK to have all declared errors in a single error.go file :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, I also don't think the separate types is very go idiomatic. https://golang.org/src/io/io.go has some exported errors that I have used before;
var EOF = errors.New("EOF")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussing idomatic errors in Go is tricky as they are mid-transition ;) We need to go with what was best in 1.12 I think as some of the newer things we can't opt in to without upgrading our version required.
That said I don't remember what best practice was 3 versions ago.
// Since: 2.0.0 | ||
Authority() string | ||
|
||
// Path should return the URI path, as defined by IETF RFC3986. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to add to this doc to make it clear that one must not assume a file path.
As we use URI to replace file handling I have heard many assume that "IF you would just implement Path()
then I could send it to my file managent code...
// to a particular URI scheme. | ||
// | ||
// Since 2.0.0 | ||
Init() func() error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am also not sure this needs to be included. I envisioned the initialization going the other way, where the developer initializes a repository, most likely by importing a third party library, which runs its func init()
, which registers itself with the storage API (like when importing "image/png")
// repository. | ||
// | ||
// Since 2.0.0 | ||
func RegisterCopy(scheme string, copyImplementation func(fyne.URI, fyne.URI) error) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
func RegisterCopy(scheme string, copyImplementation func(fyne.URI, fyne.URI) error) error { | |
func RegisterCopy(scheme string, copy func(fyne.URI, fyne.URI) error) error { |
// with a URIOperationNotSupported error. | ||
// | ||
// Since 2.0.0 | ||
func Listable(u fyne.URI) (bool, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or IsListable
package storage | ||
|
||
// Declare conformance with Error interface | ||
var _ error = URIOperationImpossible |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, I also don't think the separate types is very go idiomatic. https://golang.org/src/io/io.go has some exported errors that I have used before;
var EOF = errors.New("EOF")
@andydotxyz @stuartmscott @AlbinoGeek Per our meeting today, I have written a revised proposal (link). I think this represents our current consensus based on what we discussed.
I plan to resume work on this on Monday (or maybe a little on Sunday). |
Description:
This PR tracks work being done to re-work URIs based on prior discussion (#1233) for the 1.4 release, and also addresses #1509. In particular, it moves several functions into the URI interface that were previously stand-alone functions.
Checklist:
Where applicable: