1. 32
    Practical Dependency Injection in Python python hakibenita.com
    1. 10

      Why waste such a thorough article with a stupid clickbait title? At least someone edit the lobste.rs title to something else?

      1. 4

        You have the power to suggest title edits. Click the 'suggest' link button at the top under the title.

        1. 4

          We're generally against changing the title of a submission away form what it actually is, except to remove authors and such.

          1. 2

            Sure, but anyone can suggest anything. I was just informing them that they don't have to ask someone to change it, they can suggest changes themselves. I wasn't arguing that the existing title is/isn't wrong.

        2. 1

          I don't think it's worth subverting the author (Who's a lobster user!)'s intent and changing the title of the post, but I agree that it's definitely not indicative of the quality of the content within.

          1. 3

            I made a suggestion with the subtitle of the post "Practical Dependency Injection in Python" because it seems to be much more descriptive of the containing content and doesn't subvert the author, as that's really a secondary title. Still, it can be approved or denied.

        3. 8

          Like every other problem in Python, there are libraries that provide a solution. Two libraries that stand out are freezegun and libfaketime. Both provide the ability to mock time at different levels. However, resorting to external libraries is a luxury only developers of legacy system can afford. For new projects, or projects that are small enough to change, there are other alternatives that can keep the project free of these dependencies.

          The article only touches on libraries like freezegun, using a rather dismissive argument that "only developers of legacy systems can afford" them, but I tend to disagree - libraries like these are designed as conveniences rather than crutches. One example I have is testing token validation (in our case JWTs) - you can test the same token right before it's supposed to be valid, during the valid period and after, without having to dig into the internals of the PyJWT library. With freezegun, this was trivial. When you don't control the code actually calling datetime.now(), this method of mocking out dates is quite a bit easier to control.

          Note that there are plenty of good examples here... in particular some of the stuff around designing Protocols is super useful, but similar to the clickbait-style title, the datetime portion seems to brush past a valid answer because it doesn't fit the narrative of the post.

          1. 2

            I agree that if you use an external library with an API like the one you are describing, may force you to use libraries such as libfaketime. Not because it's the best, or the right way, but because you have to.

            Point of the article is that the library API can possibly be changed so that you won't have to use libfaketime. Instead, the library can provide you with a simpler way of testing the token. For example, provide an argument that sets the time the token is validated at, like the article suggests.

          2. 6

            An interesting article! I personally tend to associate dependency injection with brain bruisingly complex Java frameworks like Spring or Guice, but as explained in this article I can at least see where the extra complexity is clearly adding value.

            That said, the article uses datetime.now() as an example of where DI can help, but I found myself wondering "Why not just use a test fake instead?"

            1. 8

              I was wondering why either mocking the date class was out of scope ie

              import datetime
              
              def test_tomorrow(mocker, monkeypatch):
                  FakeDate = mocker.magicMock()
                  fake_now = mocker.MagicMock()
                  FakeDate.now = fake_now
                  fake_now.return_value = datetime.date(1, 2, 3)
                  with monkeypatch.context() as c:
                      # notice how we override both the class and function with a mock:
                      c.setattr(datetime, “date”, FakeDate)
                      assert tomorrow() == fake_now.return_value
              

              You don’t have to override datetime.date inside the datetime module! Only the reference inside the module that uses it!! The above pattern is very common in our tests.

              1. 4

                That's interesting. I was looking for different ways to mock datetime (mainly for research though, because DI hold additional benefits over Mock) and didn't find any. Thanks!

            2. 2

              Nitpick, but because of Python's stateful generators the implementation of FakeIpLookupService could be unpredictable if that iterable is shared by any other referer.

              Example of this possibly unexpected behavior:

              >>> xs=(2*x for x in range(10))
              >>> xs
              <generator object <genexpr> at 0x1078047d0>
              >>> i1=iter(xs)
              >>> i2=iter(i1)
              >>> next(xs)
              0
              >>> next(i2)
              2
              
              1. [Comment removed by author]