Danny Hooper <hooper@google.com> [Sat, 03 Mar 2018 14:08:44 -0800] rev 37183
fix: new extension for automatically modifying file contents
This change implements most of the corresponding proposal as discussed at the
4.4 and 4.6 sprints: https://www.mercurial-scm.org/wiki/AutomaticFormattingPlan
This change notably does not include parallel execution of the formatter/fixer
tools. It does allow for implementing that without affecting other areas of the
code.
I believe the test coverage to be good, but this is a hotbed of corner cases.
Differential Revision: https://phab.mercurial-scm.org/D2897
Gregory Szorc <gregory.szorc@gmail.com> [Fri, 30 Mar 2018 11:11:42 -0700] rev 37182
tests: ignore zope packages when running pyflakes
Differential Revision: https://phab.mercurial-scm.org/D2972
Gregory Szorc <gregory.szorc@gmail.com> [Wed, 21 Mar 2018 19:48:36 -0700] rev 37181
repository: define interface for local repositories
Per discussions on the mailing list and at the 4.4 and 4.6 sprints,
we want to start defining interfaces for local repository primitives
so that we a) have a better idea of what the formal interface for
various types is b) can more easily introduce alternate implementations
of various components (e.g. in Rust).
We have previously implemented interfaces that declare the peer and
wire protocol APIs using the abc module.
This commit introduces a monolithic interface for the localrepository
class. It uses zope.interface - not abc - for defining and declaring
the interface.
The newly defined "completelocalrepository" interface is objectively
horrible. It is based on what is actually in localrepository and
doesn't represent a reasonable interface definition IMO. There's lots
of... unwanted garbage in the interface. In other words, it reflects
the horrible state of the localrepository "god object." But this is
fine: a goal of this commit is to get the interface defined so that
we have an interface. Future commits can refactor the interface
into sub-interfaces, remove unwanted public attributes, etc.
I attempted to define reasonable docstrings for the various interface
members. But there are so many of them and I didn't know what some are
used for. So I was lazy in a number of places and didn't write
docstrings or detailed usage docs.
Also, the members of the interface are defined in the order they are
declared in localrepo.py. This revealed that the grouping of things
in localrepo.py is... odd.
The localrepository class now declares that it implements our newly
defined interface. Unlike abc, zope.interface doesn't check interface
conformance at type creation time (abc uses __metaclass__ magic to
validate interface conformance when a type is created - usually at
module import time). It does provide some functions for validating
class and object conformance with declared interfaces. We add these
checks to test-check-interfaces.py. We /could/ validate at run-time.
But we hold off for now. (I'm a bit scared of doing that because of
the various ways extensions monkeypatch repo instances.)
After this commit, test-check-interfaces.py will fail if the set of
public attributes on the localrepository class or instances change
without corresponding updates to the interface. This is by design.
Differential Revision: https://phab.mercurial-scm.org/D2933
Gregory Szorc <gregory.szorc@gmail.com> [Wed, 21 Mar 2018 18:32:47 -0700] rev 37180
setup: register zope.interface packages and compile C extension
With this change, we should be able to use zope.interface in core!
Differential Revision: https://phab.mercurial-scm.org/D2932
Gregory Szorc <gregory.szorc@gmail.com> [Wed, 21 Mar 2018 18:13:40 -0700] rev 37179
thirdparty: allow zope.interface.advice to be lazily imported
The symbol from this module is only used in functions. Let's access
that symbol through its imported module so importing
zope.interface.advice can be lazy.
Differential Revision: https://phab.mercurial-scm.org/D2931
Gregory Szorc <gregory.szorc@gmail.com> [Wed, 21 Mar 2018 19:52:30 -0700] rev 37178
thirdparty: port zope.interface to relative imports
By using relative imports, we're guaranteed to get modules
vendored with Mercurial rather than other random modules
that might be in sys.path.
My editor strips trailing whitespace on save. So some minor
source code cleanup was also performed as part of this commit.
# no-check-commit because some modified lines have double newlines
Differential Revision: https://phab.mercurial-scm.org/D2930
Gregory Szorc <gregory.szorc@gmail.com> [Wed, 21 Mar 2018 19:49:07 -0700] rev 37177
thirdparty: don't make zope a namespace package
There are a gazillion zope.* packages in the wild. So zope/__init__.py
needs to be a namespace package. But in Mercurial, we have 1 zope
package. And even if we had multiple packages, they'd all be in
thirdparty/zope/. So we don't need a namespace package.
Differential Revision: https://phab.mercurial-scm.org/D2929
Gregory Szorc <gregory.szorc@gmail.com> [Wed, 21 Mar 2018 19:48:50 -0700] rev 37176
thirdparty: vendor zope.interface 4.4.3
I've been trying to formalize interfaces for various components
of Mercurial. So far, we've been using the "abc" package. This
package is "good enough" for a lot of tasks. But it quickly
falls over. For example, if you declare an @abc.abstractproperty,
you must implement that attribute with a @property or the class
compile time checking performed by abc will complain. This often
forces you to implement dumb @property wrappers to return a
_ prefixed attribute of the sane name. That's ugly.
I've also wanted to implement automated checking that classes
conform to various interfaces and don't expose other "public"
attributes.
After doing a bit of research and asking around, the general
consensus seems to be that zope.interface is the best package for
doing interface-based programming in Python. It has built-in
support for verifying classes and objects conform to interfaces.
It allows an interface's properties to be defined during __init__.
There's even an "adapter registry" that allow you to register
interfaces and look up which classes implement them. That could
potentially be useful for places where our custom registry.py
modules currently facilitates central registrations, but at a
type level. Imagine extensions providing alternate implementations
of things like the local repository interface to allow opening
repositories with custom requirements.
Anyway, this commit vendors zope.interface 4.4.3. The contents of
the source tarball have been copied into mercurial/thirdparty/zope/
without modifications.
Test modules have been removed because they are not interesting
to us.
The LICENSE.txt file has been copied so it lives next to the
source.
The Python modules don't use relative imports. zope/__init__.py
defines a namespace package. So we'll need to modify the source
code before this package is usable inside Mercurial. This will
be done in subsequent commits.
# no-check-commit for various style failures
Differential Revision: https://phab.mercurial-scm.org/D2928
Martin von Zweigbergk <martinvonz@google.com> [Thu, 29 Mar 2018 23:05:41 -0700] rev 37175
context: set repo property in basectx
It seems like a good practice to call the super constructor. Let's
start by passing the repo along to basectx so it can assign it to a
private attribute. We should perhaps pass the rev and node along as
well, but that requires more work before it can be done.
Differential Revision: https://phab.mercurial-scm.org/D2970
Martin von Zweigbergk <martinvonz@google.com> [Thu, 29 Mar 2018 22:51:45 -0700] rev 37174
context: move reuse of context object to repo.__getitem__ (API)
As an example of how weird the basectx.__new__ is: whenever you create
a workingctx, basectx.__new__ gets called first. Since our __new__ has
a "changeid" argument as second parameter, when create the
workingctx(repo, text="blah"), the text gets bound to
"changeid". Since a string isn't a basectx, our __new__ ends up not
doing anything funny, but that's still very confusing code.
Another case is metadataonlyctx.__new__(), which I think exists in
order to prevent metadataonlyctx.__init__'s third argument
(originalctx) from being interpreted as a changeid in
basectx.__new__(), thereby getting reused.
Let's move this to repo.__getitem__ instead, where it will be pretty
obvious what the code does.
After this patch, changectx(ctx) will be an error (it will fail when
trying to see if it's a 20-byte string).
Differential Revision: https://phab.mercurial-scm.org/D2969