Skip to content

ABCMeta for interfaces #167

wants to merge 706 commits into from
exupero commented Dec 10, 2012

Currently class interfaces are implemented with AbstractMethodCall exceptions and multiple inheritance. This strategy only catches classes that don't fully implement their interfaces when someone stumbles onto a method that hasn't been implemented. Python's abstract base classes support catching classes that don't fully implement an interface when the classes are defined.

These changes only modify a couple of interface classes to use ABCMeta and the abstractmethod decorator, but following the pattern for other interface classes should be relatively straight-forward. (In the process of implementing the interfaces, I found several definitions that didn't implement all their abstract methods and took a stab at rectifying it. Fixes and improvements are welcome.)


Ha! I've got a half finished (supports try/finally currently, working on try/catch) implementation of try on my local repo :) It might be wise to work together, as the bytecode for try and friends is rather complex. Shall I push it out to a separate branch on this repo?

Oooh, I feared something like this. Just worked on the preliminaries, did no glueing together yet. Since it was quite isolated in I thought it safe to check in without breaking anything. But I do not want to disturb your efforts.
As I did not create any finally or catch glueing-bytecode it might be best you overwrite my changes later.
But if you want, you can send your current code to me directly and I could integrate it. Write a few tests perhaps?
I would not create a separate branch. Perhaps you could checkin into your fork?
Don't know how this is done with git normally.

The way I've implemented it so far is quite modular. One compileTry function to do the argument parsing etc, which then delegates to a compileTryFinally function to compile that specific form, meaning that multiple forms can be implemented in parallel. I'll push it to my fork on github, and then we can see where we stand :)

bluepeppers and others added some commits Mar 25, 2012
@bluepeppers bluepeppers Added compileTry function with support for try/finally.
No tests, as it's a pain to test for side affects.
@halgari working on .cljc writing...trying a different method d5354a5
@halgari my bad... bfb0143
@bluepeppers bluepeppers Fixed problem with compileTry expecting 3 arguments not 4 for catch/e…
…xcept forms
@bluepeppers bluepeppers Fixed two occurances of no form being passed to CompilerException 1e4bde1
@bluepeppers bluepeppers Corrected the content of the catch list in compileTry 41f54df
@bluepeppers bluepeppers Added support for try/catch/catch/catch ad infinitum.
One caveat is that I'm unsure how it'll work with code that involves variables
named ___ret_val_, but I think it'll be fine.
@bluepeppers bluepeppers Fix destructuring of tuples in catch list. f21c1db
@bluepeppers bluepeppers Merge branch 'master' of 19a5fc8
@bluepeppers bluepeppers Removed duplicate implementation of try 271c856
@stirfoo stirfoo documenting persistent data structures + small bug fixes 267fc4a
@bluepeppers bluepeppers Commented out expected failing tests aeab594
@halgari implements all of defrecord except hash and __eq__ 39ffcb5
@halgari the start of extend 6e40d1e
@halgari implemented extend removed debug info 72777da
@halgari initial implementation of seqs for generators need ... try to finish 73e383d
@halgari implemented binding...not exactly fast though 3b04488
@halgari added e52e17b
@halgari Added some changes for things that I've implemented. 9bbf88c
tbaldridge added doc as per issue #90 7990b9d
tbaldridge __eq__ and __hash__ for records fixes issue #58 1ba151e
@stirfoo stirfoo PersistentVector audit, documentation, testing a39436b
@stirfoo stirfoo unicode, print protocol, reader test 59ddc69
@stirfoo stirfoo Merge branch 'master' of 9a64e5a
@stirfoo stirfoo Merge branch 'vec-map-eq' 4d8ab80
@stirfoo stirfoo MapEntry tests 4e4bb81
@stirfoo stirfoo Merge branch 'master' of c37a5b7
@stirfoo stirfoo APersistentVector tests 050e8de

Why a macro?


Should this test the result of (doc baz) as well?


I was getting some long start-up times before this commit, but it wasn't consistent. Most times the repl would appear in a couple of seconds but a few times it would take a 30s to a minute. I could ^C to kill it, restart, and the repl would again appear in a couple seconds. This happened when I ran nosetests as well, but it didn't look like Travis spent any extra time testing.

Hopefully it's just something on my end.

It seems to only occur with 2.6. If I read-only clone the repo and run python2.6 it stalls, almost every time, but will eventually drop into the repl.

This is the strange part. If I then run python2.7 it will start in a couple of seconds. If I follow that 2.7 session with 2.6, the 2.6 will start normally.

So if a 2.6 session is preceded by a 2.7 session, all is well, (every time AFAICT).

When I run 2.7 it must remove all *.pyc files. Which makes sense. If I manually delete them before each 2.6 run (including nosetests), everything is fine.


travis-ci is down. I need my green light fix!


Yes this is incorrect. I'm trying to work out the hash partitions.

stirfoo commented on cc1882c Apr 1, 2012

Some of this was ok, but it was not dealing with the root problem that (= true 1) and (= false 0) evaluate to true.


It looks like capital X and Y are used when lowercase x and y are passed in.

halgari commented on 4b1c3c5 Apr 8, 2012

I think I fixed that later on, but yeah, this is still being debugged.

anntzer and others added some commits May 17, 2012
@anntzer anntzer Update untranslated.clj. 52d781d
@anntzer anntzer Import prefers packages, fails if ns not created.
* If foo/{{,c},__pycache__/__init__.<tag>.pyc} and foo.clj
  both exist, the first one will be imported.
* The assumption that foo.clj creates a foo namespace is now enforced.
@anntzer anntzer threadBindings ctx-manager; docstrings; reorganize imports.
* with threadBindings(bindings): foo can now be used instead of
  {push,pop}ThreadBindings, wrapped in a try: ... finally: ...
* updated and added docstrings.
* group imports to top of files, removed unused ones, put them in
  alphabetical order.
@anntzer anntzer Simplified REPL logic. d59b3df
@anntzer anntzer require allows absence of namespace if unneeded.
An exception is only raised if the namespace was needed, i.e. for :as
and :use.  This is done by raising and catching a subclass of
ImportError when requireClj did not fail but did not create the
namespace either.
@anntzer anntzer Add command-line args parser, *command-line-args*.
Try `clojurepy --help`!  Closes #99.
@anntzer anntzer Better in-ns handling; tests set appropriate *ns*.
Handles constructs such as
(do (py/print *ns*) (in-ns 'a) (py/print clojure.core/*ns*))

Tests are now run with *ns* set to the namespace in which the test was
@anntzer anntzer Removed duplicate ctors keyword, symbol & var. 34e3615
@anntzer anntzer Cleanup of
* Removed circular dependency with by moving interning functions
* findOrCreate becomes Namespace constructor (which returns an already
  existing Namespace if possible).
* Removal of unused areDifferentInstancesOfSameClassName,
  findOrCreateIn, findModule.
@anntzer anntzer Debug keyword.find; remove DEFAULT_IMPORTS & unused imports.
and reorderings, and minor changes.
@anntzer anntzer Merge pull request #116 from halgari/cleanup
* New import semantics
* Removal of duplicate constructors.
@khinsen khinsen Merge branch 'master' into macroexpand to incorporate upstream changes. c8d1d45
@khinsen khinsen Updated macro-tests 525b442
@halgari Merge pull request #117 from khinsen/macroexpand
Macro expansion
@anntzer anntzer Shortening Closes #118. 60c0794
@zachallaun zachallaun defrecord and deftype generate a -> constructor fn.
This brings clojure-py further in line with jvm-clojure, and will
make porting records and types simpler.
@halgari Merge pull request #120 from zachallaun/type-and-record-helpers
Looks good to me. Thanks for this.
@zachallaun zachallaun Fix issue-121: conj onto nil 81e2c67
@zachallaun zachallaun Refactor Atom.swap() and translate swap!
Atom.swap contained a bug that became apparent when you tried to call
swap() with more than 3 arguments; apply() was being called with the IFn
and 3 extra arguments, when apply only takes two arguments, an IFn and a

Even still, the use of apply() is deprecated for the use of the splat
*args syntax. Atom.swap() was refactored to take this into account, and
to fix the bug.

swap! was then translated into core.clj.
@halgari Merge pull request #123 from zachallaun/atom-swap
Refactor Atom.swap() and translate swap!
@halgari Merge pull request #122 from zachallaun/issue-121
Fix issue-121: conj onto nil
@zachallaun zachallaun Implement true? and false? in terms of =
Fixes issue-124, where (true? true), etc., was throwing an
AttributeError, because bool doesn't implement __eq__(). Some core
functions have been moved around to allow true? and false? to be
implemented in terms of =. Tests have also been added for these two
@halgari Merge pull request #125 from zachallaun/issue-124
Implement true? and false? in terms of =
@pepijndevos pepijndevos basic features d8b998d
@halgari Merge pull request #127 from pepijndevos/master
ThreadPool based futures
@anntzer anntzer findNS queries __aliases__ with Symbol, not a str.
Closes #126.
Also add is_package method to the MetaImporter.
@anntzer anntzer Add current folder to module search path.
Closes #128, #131.
@anntzer anntzer Add the current directory to sys.path.
Previously, only the directory where the script was installed was added.
Closes #130.
@halgari added IPending to futures 551013f
@anntzer anntzer Allow empty bindings for loop form.
Closes #132.
@anntzer anntzer Merge branch 'master' of 0d2bf44
@anntzer anntzer Avoid infinite loop when method calls protocol.
Closes #133 by momentarily setting method name to "_" so that delegation
to protocol is properly resolved.

Also closes #134.

And updates the docstring of reify to something actually relevant to
@brandonbloom brandonbloom Implement time macro e9ee9cc
Eric Shull Merge pull request #137 from brandonbloom/time-macro
Implement time macro.
@lfranchi lfranchi Find should return nil entry is not found in a map
Previously it was returning a truthy [k nil] MapEntry. Test are
included to ensure correct behaviour
@lfranchi lfranchi Support assoc on maps as well as assocN bae10d2
@lfranchi lfranchi Port replace, with tests 3a03b49
@lfranchi lfranchi Move over reductions with tests. c005541
@lfranchi lfranchi Use more robust test that is not implementation-dependent 7d808fd
@anntzer anntzer Merge pull request #138 from lfranchi/porting
Port two small functions + supporting changes over, plus tests.
@lfranchi lfranchi Support try containing multiple statements, and add tests
The body of a try statement should be an implicit do, returning
the value of the last executed statement. Previously the compiler
was only expecting (and allowing) one body statement for a try.
@lfranchi lfranchi Port with-redefs-fn and with-redefs, with tests 0666275
@lfranchi lfranchi Use a more elegant way of checking for subforms cdff689
@lfranchi lfranchi Remove useless line 8df3163
@lfranchi lfranchi Make test name unique 00ae2fd
@anntzer anntzer Merge pull request #139 from lfranchi/try-redefs
Fix compiling of try statements to allow implicit-do body
@lfranchi lfranchi Basic ref f6f5c23
@lfranchi lfranchi Fix sync and dosync macros, and add test 9cf6d66
@lfranchi lfranchi Add SharedLock (read-write lock) + deps in clojure.utils e98471a
@lfranchi lfranchi Add ms_since_epoch helpers 480b2a5
@lfranchi lfranchi Add skeleton of STM'ed Ref, and initial thread-local LockingTransaction
Disable SharedLock debug and make currentVal more private
@lfranchi lfranchi Add more tests for existing code 495627f
@lfranchi lfranchi Use interop syntax for calling @classmethod f1b6474
@lfranchi lfranchi Begin fleshing out LockingTransaction + tests: add misc functions d56d74e
@lfranchi lfranchi Refactor test code to use a contextmanager and with statement 383b857
@lfranchi lfranchi Add first real transaction bits: _lock, _barge, etc. Plus tests. af2a058
@lfranchi lfranchi Implement LockingTransaction.getRef() + test 2ecdc5d
@lfranchi lfranchi Add doSet() and test 594b6bf
@lfranchi lfranchi Add LockingTransaction.doEnsure and tests 9649d32
@lfranchi lfranchi Initial working :D 4e41ab5
@lfranchi lfranchi Add a basic test for running transactions from start to finish 83152d0
@lfranchi lfranchi Add beginning of complex multi-thread tests, synchronized w/ conditio…
…n variables
@lfranchi lfranchi Make TVal in a shared import to avoid cyclic deps f03e9d3
@lfranchi lfranchi Add test for barging, better test for faults, and more threaded test …
@lfranchi lfranchi Init startPoint to -1 not None f5d2851
@lfranchi lfranchi Don't infinite loop when traversing history chain 7157d9e
@lfranchi lfranchi Assert that a write-after-fault extended the history chain 4edb550
@lfranchi lfranchi Fix return value of refSet and commute d3e1923
@lfranchi lfranchi Add support for commutes, and some basic tests d6fe8cd
@lfranchi lfranchi Implement java's CountdownLatch as a threading.Event c0f13fa
@lfranchi lfranchi Attempt a test for commute being better than alter, but it's exposing…
… some race conditions in high contention alter cases
@lfranchi lfranchi Fix high-concurrency transaction bugs. Phew.
Starting refs at 1 before the first transaction ensures that the first started
transaction is able to read the first created ref directly.

Stop must actually set the status of the Info object to the new status,
otherwise a transaction can try to barge itself (it'll see the old/dead info
in a ref and it thinks it is still alive)
@lfranchi lfranchi Tweak debug output and fix alter/commute test to assert proper final …
@lfranchi lfranchi Fix missing return value in _barge, so if we actually barge, we repor…
…t it
@lfranchi lfranchi Use Event variables instead of Conditions, they are the proper tool f…
…or the job
@lfranchi lfranchi Send watch notifiers d8088e4
@lfranchi lfranchi Add ensure clojure bridge and core-tests for it d4bbae7
@lfranchi lfranchi Use collections.OrderedDict instead of a normal dict d6b1094
@lfranchi lfranchi Cleanups from review comments 97074f5
@lfranchi lfranchi Fix function signatures to not unpack arguments in the wrong place fbe7868
Rainer Schuster bug-fix: ArrayChunk attribute nth not implemented
filter and map-indexed are using the nth member function
ArrayChunk e.g. created by range doesn't implement it and
both funcs are implemented before nth is defined
Rainer Schuster changed ArrayChunk.nth member to call __getitem__ 51e0631
Eric Shull Merge pull request #143 from schuster-rainer/arraychunk-bug
bug-fix: ArrayChunk attribute nth not implemented
@lfranchi lfranchi Fix assert condition to >=
Fix tests to use new ref.alter/commute param syntax
@lfranchi lfranchi Don't use OrderedDict as it's python 2.7+
Remove useless method that added a python2.7 dep for no reason
Peter Seibel Code cleanup w/ peter seibel. Also, Cleanup the cleanup. e73ff28
@lfranchi lfranchi Remove OrderedDict comment and slightly rework thread_local naming 8bf19a9
@anntzer anntzer Merge pull request #141 from 'lfranchi/refs'
@anntzer anntzer Fix `not` for clj-truthiness-#146; travis for 2.6. 2760d24
@anntzer anntzer Fix nil arg for str; stopgap for unittest in 2.6. fd29627
@anntzer anntzer Fix #148 (off-by-one in string/split), with test. f45f8e3
@anntzer anntzer Fix var for Vars out of clojure.core (#147). 56aa28b
@anntzer anntzer Set docstrings in clojure.string, fix #147. dff471f
Eric Shull Cleanup.
- Remove some unused AbstractMethodCall imports.
- Add 'count' method to APersistentVector.
- Whitespace changes.
Eric Shull Merge branch 'master' of 813b589
Eric Shull More cleanup.
- Remove inheritance from 'object' when 'object' is already included in class hierarchy.
- Remove documentation of date when documentation was added.
- Whitespace.
Eric Shull Add code for ABCMeta, but can't compile. ed16f65
Eric Shull Finish implementing abstract methods for IPersistentCollection. 902dd8f
anntzer commented Dec 10, 2012

I really like the idea (the whole implementation of interfaces is shaky at best, IMHO, but there is a lot of work to be done to improve that). Some thoughts:
1/ If we are going to use abstractmethod, then it makes sense to deprecate the AbtractMethodCall exception (the body of the abstractmethod should be pass, or more pythonically a docstring).
2/ @halgari suggested, at some point, to completely get rid of java-style interfaces and use protocols as the base abstraction for clojure-py (just as clojurescript does). The main difference is that protocols do not actually enforce that their extenders implement all their methods (something I think is poor language design, but well...); on the other hand it should be reasonably easy to modify the code for ABCs (i.e., create a new metaclass inspired from ABCMeta) so that it does not refuse to instantiate subclasses which do not override all abstractmethods, but just throws some warning when that happens.

jimpil commented on b547f61 Jun 30, 2013

time.clock() is not at all accurate on Unix-y systems...time.time() should be used instead. Try the current version of 'time' against something that takes less than 10ms and you'll see what I mean...Also, if time.time() is used it's better to round to 5-7 digits instead of 3. I think Clojure jvm gives 7 digits back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.