replacing __dict__ with an OrderedDict

Discussion in 'Python' started by Ulrich Eckhardt, Jan 6, 2012.

  1. Hi!

    The topic explains pretty much what I'm trying to do under Python
    2.7[1]. The reason for this is that I want dir(SomeType) to show the
    attributes in the order of their declaration. This in turn should
    hopefully make unittest execute my tests in the order of their
    declaration[2], so that the output becomes more readable and structured,
    just as my test code (hopefully) is.

    I've been toying around with metaclasses, trying to replace __dict__
    directly, or using type() to construct the class, but either I hit
    read-only attributes or the changes seem to be ignored.

    As additional thought (but I'm not there yet), I guess that if I want
    dir(some_object) to be ordered similarly, I will also have to perform
    some steps on instance creation, not only on class creation, right?

    Thanks for any suggestions!

    Uli


    [1] I'm stuck with 2.x for now, from what I found it would be easier
    using 3.x.

    [2] No, don't tell me that the tests should run in any order. It's not
    the case that my tests depend on each other, but if one basic test for
    the presence of an API fails, the elaborate tests using that API will
    obviously fail, too, and I just want to take the first test that fails
    and analyse that instead of guessing the point to start debugging from
    the N failed tests.
     
    Ulrich Eckhardt, Jan 6, 2012
    #1
    1. Advertising

  2. Ulrich Eckhardt

    Lie Ryan Guest

    On 01/06/2012 08:48 PM, Ulrich Eckhardt wrote:
    > Hi!
    >
    > The topic explains pretty much what I'm trying to do under Python
    > 2.7[1]. The reason for this is that I want dir(SomeType) to show the
    > attributes in the order of their declaration. This in turn should
    > hopefully make unittest execute my tests in the order of their
    > declaration[2], so that the output becomes more readable and structured,
    > just as my test code (hopefully) is.


    IMO that's a futile effort, first, because as you already know, the test
    should not rely on the order. If you want the result to be printed in a
    certain order, that's a display issue, not testing order issue. I guess
    you would have better luck doing what you want by customizing the
    TestResult or TestRunner.
     
    Lie Ryan, Jan 6, 2012
    #2
    1. Advertising

  3. Ulrich Eckhardt

    Peter Otten Guest

    Ulrich Eckhardt wrote:

    > The topic explains pretty much what I'm trying to do under Python
    > 2.7[1]. The reason for this is that I want dir(SomeType) to show the
    > attributes in the order of their declaration. This in turn should
    > hopefully make unittest execute my tests in the order of their
    > declaration[2], so that the output becomes more readable and structured,
    > just as my test code (hopefully) is.
    >
    > I've been toying around with metaclasses, trying to replace __dict__
    > directly, or using type() to construct the class, but either I hit
    > read-only attributes or the changes seem to be ignored.


    Alternatively you can write your own test loader:

    $ cat ordered_unittest2.py
    import unittest

    class Test(unittest.TestCase):
    def test_gamma(self):
    pass
    def test_beta(self):
    pass
    def test_alpha(self):
    pass

    class Loader(unittest.TestLoader):
    def getTestCaseNames(self, testCaseClass):
    """Return a sequence of method names found within testCaseClass
    sorted by co_firstlineno.
    """
    def first_lineno(name):
    method = getattr(testCaseClass, name)
    return method.im_func.__code__.co_firstlineno

    function_names = super(Loader, self).getTestCaseNames(testCaseClass)
    function_names.sort(key=first_lineno)
    return function_names


    if __name__ == "__main__":
    unittest.main(testLoader=Loader())

    $ python2.7 ordered_unittest2.py -v
    test_gamma (__main__.Test) ... ok
    test_beta (__main__.Test) ... ok
    test_alpha (__main__.Test) ... ok

    ----------------------------------------------------------------------
    Ran 3 tests in 0.001s

    OK
    $
     
    Peter Otten, Jan 6, 2012
    #3
  4. Am 06.01.2012 12:43, schrieb Lie Ryan:
    > On 01/06/2012 08:48 PM, Ulrich Eckhardt wrote:
    >> Hi!
    >>
    >> The topic explains pretty much what I'm trying to do under Python
    >> 2.7[1]. The reason for this is that I want dir(SomeType) to show the
    >> attributes in the order of their declaration. This in turn should
    >> hopefully make unittest execute my tests in the order of their
    >> declaration[2], so that the output becomes more readable and structured,
    >> just as my test code (hopefully) is.

    >
    > IMO that's a futile effort, first, because as you already know, the test
    > should not rely on the order. If you want the result to be printed in a
    > certain order, that's a display issue, not testing order issue.


    I'm not sure if you just -ahem- enjoy Usenet discussions, but please
    read the footnote that explains that I don't want to discuss this part
    and why you are actually wrong with your partial understanding of the
    issue. ;^)


    > I guess you would have better luck doing what you want by customizing
    > the TestResult or TestRunner.


    True, perhaps, but doing it this way would be more fun and easier
    reusable in other cases where the default order is not desirable. I can
    also go and name the test functions test_000 to test_009 to get results
    quickly, if that was the only goal.

    Cheers!

    Uli
     
    Ulrich Eckhardt, Jan 6, 2012
    #4
  5. Am 06.01.2012 12:44, schrieb Peter Otten:
    > Alternatively you can write your own test loader:

    [...CODE...]

    Well, actually you just did that for me and it works! ;)


    Nonetheless, I'm still wondering if I could somehow replace the dict
    with an OrderedDict.

    Thank you!

    Uli
     
    Ulrich Eckhardt, Jan 6, 2012
    #5
  6. Ulrich Eckhardt

    Ethan Furman Guest

    Ulrich Eckhardt wrote:
    > Hi!
    >
    > The topic explains pretty much what I'm trying to do under Python
    > 2.7[1]. The reason for this is that I want dir(SomeType) to show the
    > attributes in the order of their declaration. This in turn should
    > hopefully make unittest execute my tests in the order of their
    > declaration[2], so that the output becomes more readable and structured,
    > just as my test code (hopefully) is.


    I believe unittest executes tests in alphabetical order, but it does not
    display them in the same order when it prints error/fail results.

    ~Ethan~
     
    Ethan Furman, Jan 6, 2012
    #6
  7. Ulrich Eckhardt

    Ian Kelly Guest

    On Fri, Jan 6, 2012 at 6:40 AM, Ulrich Eckhardt
    <> wrote:
    > Nonetheless, I'm still wondering if I could somehow replace the dict with an
    > OrderedDict.


    In Python 3, yes. This is pretty much the entire use case for the new
    __prepare__ method of metaclasses. See the "OrderedClass" example at:
    http://docs.python.org/py3k/reference/datamodel.html#special-method-names

    Cheers,
    Ian
     
    Ian Kelly, Jan 6, 2012
    #7
  8. Ulrich Eckhardt

    Ian Kelly Guest

    On Fri, Jan 6, 2012 at 9:06 AM, Ian Kelly <> wrote:
    > On Fri, Jan 6, 2012 at 6:40 AM, Ulrich Eckhardt
    > <> wrote:
    >> Nonetheless, I'm still wondering if I could somehow replace the dict with an
    >> OrderedDict.

    >
    > In Python 3, yes.  This is pretty much the entire use case for the new
    > __prepare__ method of metaclasses.  See the "OrderedClass" example at:
    > http://docs.python.org/py3k/reference/datamodel.html#special-method-names


    That link should be:
    http://docs.python.org/py3k/reference/datamodel.html#customizing-class-creation
     
    Ian Kelly, Jan 6, 2012
    #8
  9. Ulrich Eckhardt

    Lie Ryan Guest

    On 01/07/2012 12:36 AM, Ulrich Eckhardt wrote:
    > Am 06.01.2012 12:43, schrieb Lie Ryan:
    >> On 01/06/2012 08:48 PM, Ulrich Eckhardt wrote:
    >>> Hi!
    >>>
    >>> The topic explains pretty much what I'm trying to do under Python
    >>> 2.7[1]. The reason for this is that I want dir(SomeType) to show the
    >>> attributes in the order of their declaration. This in turn should
    >>> hopefully make unittest execute my tests in the order of their
    >>> declaration[2], so that the output becomes more readable and structured,
    >>> just as my test code (hopefully) is.

    >>
    >> IMO that's a futile effort, first, because as you already know, the test
    >> should not rely on the order. If you want the result to be printed in a
    >> certain order, that's a display issue, not testing order issue.

    >
    > I'm not sure if you just -ahem- enjoy Usenet discussions, but please
    > read the footnote that explains that I don't want to discuss this part
    > and why you are actually wrong with your partial understanding of the
    > issue. ;^)


    I fully understand your issue, and I stand by my opinion. I believe
    you're misunderstanding the nature of your problem, your issue is not
    that you want a customized test order execution, but you want a
    customized view of the test result.

    That unittest executes its tests in alphabetical order is implementation
    detail for a very good reason, and good unittest practice dictates that
    execution order should never be defined (some even argued that the
    execution order should be randomized). If the test runner turns out to
    execute tests concurrently, that should not cause problems for a
    well-designed test. Displaying the test results in a more convenient
    order for viewing is what you really wanted in 99.99% of the cases.

    > > I guess you would have better luck doing what you want by customizing
    > > the TestResult or TestRunner.

    >
    > True, perhaps, but doing it this way would be more fun and easier
    > reusable in other cases where the default order is not desirable. I can
    > also go and name the test functions test_000 to test_009 to get results
    > quickly, if that was the only goal.


    Fun and easier, perhaps. Except that it solves the wrong problem.
     
    Lie Ryan, Jan 6, 2012
    #9
  10. Ulrich Eckhardt

    Ian Kelly Guest

    On Fri, Jan 6, 2012 at 10:01 AM, Lie Ryan <> wrote:
    > That unittest executes its tests in alphabetical order is implementation
    > detail for a very good reason, and good unittest practice dictates that
    > execution order should never be defined (some even argued that the execution
    > order should be randomized). If the test runner turns out to execute tests
    > concurrently, that should not cause problems for a well-designed test.
    > Displaying the test results in a more convenient order for viewing is what
    > you really wanted in 99.99% of the cases.


    Randomizing the order is not a bad idea, but you also need to be able
    to run the tests in a consistent order, from a specific random seed.
    In the real world, test conflicts and dependencies do happen, and if
    we observe a failure, make a change, rerun the tests and observe
    success, we need to be able to be sure that we actually fixed the bug,
    and that it didn't pass only because it was run in a different order.

    Concurrent testing is a bad idea for this reason -- it's not
    repeatable (testing concurrency, OTOH, is a perfectly fine thing to be
    thinking about).

    Cheers,
    Ian
     
    Ian Kelly, Jan 6, 2012
    #10
  11. Ulrich Eckhardt

    Lie Ryan Guest

    On 01/07/2012 04:20 AM, Ian Kelly wrote:
    > On Fri, Jan 6, 2012 at 10:01 AM, Lie Ryan<> wrote:
    >> That unittest executes its tests in alphabetical order is implementation
    >> detail for a very good reason, and good unittest practice dictates that
    >> execution order should never be defined (some even argued that the execution
    >> order should be randomized). If the test runner turns out to execute tests
    >> concurrently, that should not cause problems for a well-designed test.
    >> Displaying the test results in a more convenient order for viewing is what
    >> you really wanted in 99.99% of the cases.

    >
    > Randomizing the order is not a bad idea, but you also need to be able
    > to run the tests in a consistent order, from a specific random seed.
    > In the real world, test conflicts and dependencies do happen, and if
    > we observe a failure, make a change, rerun the tests and observe
    > success, we need to be able to be sure that we actually fixed the bug,
    > and that it didn't pass only because it was run in a different order.
    >
    > Concurrent testing is a bad idea for this reason -- it's not
    > repeatable (testing concurrency, OTOH, is a perfectly fine thing to be
    > thinking about).


    Concurrent testing is perfectly fine strategy in the case where you have
    thousands of tests and running them synchronously will just take too
    long. Certainly it makes it harder to repeat the test if there is any
    sort of dependency in the tests, but when you have the large number of
    tests, the benefit may exceeds the drawbacks.
     
    Lie Ryan, Jan 6, 2012
    #11
  12. On 6 January 2012 11:44, Peter Otten <> wrote:
    > class Loader(unittest.TestLoader):
    >    def getTestCaseNames(self, testCaseClass):
    >        """Return a sequence of method names found within testCaseClass
    >        sorted by co_firstlineno.
    >        """


    That's a clever trick!

    --
    Arnaud
     
    Arnaud Delobelle, Jan 6, 2012
    #12
  13. On 6 January 2012 13:40, Ulrich Eckhardt
    <> wrote:
    > Am 06.01.2012 12:44, schrieb Peter Otten:
    >
    >> Alternatively you can write your own test loader:

    >
    > [...CODE...]
    >
    > Well, actually you just did that for me and it works! ;)
    >
    >
    > Nonetheless, I'm still wondering if I could somehow replace the dict with an
    > OrderedDict.


    No, you can't.

    --
    Arnaud
     
    Arnaud Delobelle, Jan 6, 2012
    #13
  14. On Sat, 07 Jan 2012 04:01:44 +1100, Lie Ryan wrote:

    > On 01/07/2012 12:36 AM, Ulrich Eckhardt wrote:
    >> True, perhaps, but doing it this way would be more fun and easier
    >> reusable in other cases where the default order is not desirable. I can
    >> also go and name the test functions test_000 to test_009 to get results
    >> quickly, if that was the only goal.

    >
    > Fun and easier, perhaps. Except that it solves the wrong problem.


    Fun and easier, and a terrible thing to do. Contrast:

    "test_binsearch_tuple is failing. What does that mean?"
    "Oh, that tests that binsearch works on a tuple. You need to look at the
    BinSearch.search_tuple method and see what it's doing."

    with

    "test_047 is failing. What does that mean?"
    "How the hell should I know?"


    Debugging is hard enough without obfuscating the test names. You wouldn't
    write a function called "func_009", why write one called "test_009"?



    --
    Steven
     
    Steven D'Aprano, Jan 7, 2012
    #14
  15. On Fri, 06 Jan 2012 10:20:28 -0700, Ian Kelly wrote:

    > On Fri, Jan 6, 2012 at 10:01 AM, Lie Ryan <> wrote:
    >> That unittest executes its tests in alphabetical order is
    >> implementation detail for a very good reason, and good unittest
    >> practice dictates that execution order should never be defined (some
    >> even argued that the execution order should be randomized). If the test
    >> runner turns out to execute tests concurrently, that should not cause
    >> problems for a well-designed test. Displaying the test results in a
    >> more convenient order for viewing is what you really wanted in 99.99%
    >> of the cases.

    >
    > Randomizing the order is not a bad idea, but you also need to be able to
    > run the tests in a consistent order, from a specific random seed. In the
    > real world, test conflicts and dependencies do happen,


    In the real world, test conflicts and dependencies are bugs in your test
    suite that should be fixed, like any other bug in code. The fact that it
    is test code that is failing is irrelevant.

    Also in the real world, sometimes it is too hard to fix a bug and you
    just live with it.


    > and if we observe
    > a failure, make a change, rerun the tests and observe success, we need
    > to be able to be sure that we actually fixed the bug, and that it didn't
    > pass only because it was run in a different order.


    Every test should stand alone. You should be able to isolate each and
    every test and run it without the others. If you can't, your test suite
    is buggy. (Chances are good that most test suites are buggy. After all,
    who writes tests for their tests? That's just the start of an infinite
    regress with rapidly diminishing benefit.)

    You may not be able to run tests *simultaneously*, due to clashes
    involving external resources, but you should be able to run them in
    random order.



    --
    Steven
     
    Steven D'Aprano, Jan 7, 2012
    #15
  16. Ulrich Eckhardt

    Lie Ryan Guest

    On 01/07/2012 11:49 AM, Steven D'Aprano wrote:
    > You may not be able to run tests*simultaneously*, due to clashes
    > involving external resources, but you should be able to run them in
    > random order.


    tests that involves external resources should be mocked, although there
    are always a few external resources that cannot be mocked, those are the
    exceptions not the rule; a concurrent test runner might have mechanisms
    to mark them to be run synchronously.
     
    Lie Ryan, Jan 7, 2012
    #16
  17. Ulrich Eckhardt

    Ian Kelly Guest

    On Fri, Jan 6, 2012 at 5:49 PM, Steven D'Aprano
    <> wrote:
    > In the real world, test conflicts and dependencies are bugs in your test
    > suite that should be fixed, like any other bug in code. The fact that it
    > is test code that is failing is irrelevant.


    I agree 100%, but none of that changes my point, which is that when
    that this sort of problem arises, you need to be able to test
    consistently to know that the bug is actually fixed.

    > Every test should stand alone. You should be able to isolate each and
    > every test and run it without the others.


    Ideally, yes. I'm talking about *unintentional* conflicts and dependencies.
     
    Ian Kelly, Jan 7, 2012
    #17
  18. Ulrich Eckhardt

    Eelco Guest

    i havnt read every post in great detail, but it doesnt seem like your
    actual question has been answered, so ill give it a try.

    AFAIK, changing __dict__ to be an ordereddict is fundamentally
    impossible in python 2. __dict__ is a builtin language construct
    hardcoded into the C API. There is no way to mess with it.

    Apparently this is different in python 3, but I dont know much about
    that.
     
    Eelco, Jan 8, 2012
    #18
  19. Ulrich Eckhardt

    alex23 Guest

    On Jan 7, 2:06 am, Ian Kelly <> wrote:
    > <> wrote:
    > > Nonetheless, I'm still wondering if I could somehow replace the dict with an
    > > OrderedDict.

    >
    > In Python 3, yes.  This is pretty much the entire use case for the new
    > __prepare__ method of metaclasses.  See the "OrderedClass" example[...]


    This isn't accurate. The OrderedClass example uses an OrderedDict to
    remember the method creation order:

    def __new__(cls, name, bases, classdict):
    result = type.__new__(cls, name, bases, dict(classdict))
    result.members = tuple(classdict)
    return result

    The instantiated objects __dict__ will still be a regularly
    dictionary, while the assignment order is stored in the class
    attribute .members.
     
    alex23, Jan 9, 2012
    #19
  20. Ulrich Eckhardt

    Lie Ryan Guest

    On 01/09/2012 09:03 AM, Eelco wrote:
    > i havnt read every post in great detail, but it doesnt seem like your
    > actual question has been answered, so ill give it a try.
    >
    > AFAIK, changing __dict__ to be an ordereddict is fundamentally
    > impossible in python 2. __dict__ is a builtin language construct
    > hardcoded into the C API. There is no way to mess with it.
    >
    > Apparently this is different in python 3, but I dont know much about
    > that.


    Actually the primary question has been answered by Ian Kelly which
    suggested __prepare__ for Python 3, and Peter Otten posted a code for a
    custom TestLoader that will essentially do what the OP wanted.

    I was just suggesting that what the OP thinks he wants is quite likely
    not what he actually wants.
     
    Lie Ryan, Jan 9, 2012
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    1
    Views:
    360
    Alex Martelli
    Nov 6, 2003
  2. Derek Fountain

    When is a __dict__ not a __dict__?

    Derek Fountain, Apr 21, 2004, in forum: Python
    Replies:
    1
    Views:
    350
    John Roth
    Apr 21, 2004
  3. Jonathan Fine
    Replies:
    0
    Views:
    455
    Jonathan Fine
    Nov 17, 2009
  4. Gnarlodious

    Python 3: Plist as OrderedDict

    Gnarlodious, Feb 9, 2010, in forum: Python
    Replies:
    6
    Views:
    867
    Gnarlodious
    Feb 9, 2010
  5. Steven D'Aprano
    Replies:
    0
    Views:
    311
    Steven D'Aprano
    Jan 9, 2012
Loading...

Share This Page