Skip to content

Add pure Python implementation of datetime module to CPython #52237

Closed

Description

@briancurtin
BPO 7989
Nosy @malemburg, @tim-one, @brettcannon, @rhettinger, @amauryfa, @mdickinson, @abalkin, @pitrou, @vstinner, @giampaolo, @merwok, @bitdancer, @briancurtin, @durban
Files
  • PyPy-2.7.diff
  • datetime-sandbox-pypy.diff
  • issue7989-2.7-3.2.diff
  • issue7989-cmp.diff
  • issue5288-proto.diff
  • issue7989.diff: Patch against py3k
  • issue7989b.diff
  • issue7989c.diff
  • issue7989d.diff
  • datetimetester.py
  • issue7989e.diff
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/abalkin'
    closed_at = <Date 2010-07-23.19:32:38.815>
    created_at = <Date 2010-02-22.16:22:07.251>
    labels = ['type-feature', 'library']
    title = 'Add pure Python implementation of datetime module to CPython'
    updated_at = <Date 2010-07-23.19:32:38.814>
    user = 'https://github.com/briancurtin'

    bugs.python.org fields:

    activity = <Date 2010-07-23.19:32:38.814>
    actor = 'belopolsky'
    assignee = 'belopolsky'
    closed = True
    closed_date = <Date 2010-07-23.19:32:38.815>
    closer = 'belopolsky'
    components = ['Library (Lib)']
    creation = <Date 2010-02-22.16:22:07.251>
    creator = 'brian.curtin'
    dependencies = []
    files = ['17698', '17701', '17718', '17842', '17845', '17848', '17978', '17992', '18130', '18148', '18155']
    hgrepos = []
    issue_num = 7989
    keywords = ['patch']
    message_count = 91.0
    messages = ['99774', '99801', '99804', '107171', '107258', '107272', '107275', '107292', '107293', '107295', '107298', '107302', '107303', '107308', '107309', '107312', '107317', '107333', '107451', '107453', '107454', '108019', '108020', '108021', '108023', '108024', '108025', '108026', '108027', '108028', '108029', '108030', '108035', '108037', '108047', '108048', '108051', '108053', '108055', '108056', '108059', '108089', '108090', '108122', '108124', '108126', '108129', '108158', '108179', '108553', '108624', '108643', '108645', '108648', '108649', '108666', '108682', '108687', '108697', '108743', '108747', '109058', '109061', '109063', '109067', '109069', '109128', '109129', '109131', '109134', '109135', '109136', '109140', '109142', '109144', '109146', '109147', '109148', '109149', '109152', '109286', '109662', '110155', '110248', '111097', '111131', '111210', '111211', '111338', '111356', '111375']
    nosy_count = 16.0
    nosy_names = ['lemburg', 'tim.peters', 'brett.cannon', 'rhettinger', 'amaury.forgeotdarc', 'mark.dickinson', 'davidfraser', 'belopolsky', 'pitrou', 'vstinner', 'techtonik', 'giampaolo.rodola', 'eric.araujo', 'r.david.murray', 'brian.curtin', 'daniel.urban']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue7989'
    versions = ['Python 3.2']

    Activity

    1. briancurtin commented on Feb 22, 2010

      @briancurtin
      MemberAuthor

      After discussion on numerous issues, python-dev, and here at the PyCon sprints, it seems to be a good idea to move timemodule.c to _timemodule.c and convert as much as possible into pure Python. The same change seems good for datetime.c as well.

    2. added
      type-bugAn unexpected behavior, bug, or error
      stdlibStandard Library Python modules in the Lib/ directory
      on Feb 22, 2010
    3. bitdancer commented on Feb 22, 2010

      @bitdancer
      Member

      By 'convert', I believe you mean 'create a python implementation of'. That is, there's no reason to drop any c code, just to create parallel python versions when possible.

      Also note that one of the alternate implementations (IronPython I think) has an implementation of DateTime in Python that they plan to contribute.

    4. briancurtin commented on Feb 22, 2010

      @briancurtin
      MemberAuthor

      Correct, your wording is better than mine.

      I'll ask around and see where that datetime module may be and what it's state is.

    5. abalkin commented on Jun 6, 2010

      @abalkin
      Member

      As far as I remember, the datetime module started as a pure python module and was reimplemented in C around year 2003 or so. One of the important additions at that time was the C API to datetime functionality. I am afraid that with the _timemodule.c/timemodule.py split there will be more an more functionality that is awkward to access from C API.

    6. self-assigned this
      on Jun 6, 2010
    7. malemburg commented on Jun 7, 2010

      @malemburg
      Member

      Alexander Belopolsky wrote:

      Alexander Belopolsky <belopolsky@users.sourceforge.net> added the comment:

      As far as I remember, the datetime module started as a pure python module and was reimplemented in C around year 2003 or so. One of the important additions at that time was the C API to datetime functionality. I am afraid that with the _timemodule.c/timemodule.py split there will be more an more functionality that is awkward to access from C API.

      That's correct, though the main reason for rewriting the module in
      C was to gain performance - this is essential for basic types like
      date/time types.

      -1 on undoing the C rewrite.

      It would be much better to spell out the problems you mention and
      provide patches to implement solutions for them.

    8. abalkin commented on Jun 7, 2010

      @abalkin
      Member

      For the datetime module there are also a few more subtle issues that would make it difficult to make a hybrid C/Python implementation. The problem is that unlike the time module where most of the functionality is implemented in module level functions, datetime functionality is entirely in class methods.

      One may suggest to use inheritance and derive datetime classes from those implemented in _datetime.c, but this will not work because for example datetime + timedelta will return a _datetime class unless __add__ is overridden in Python. There is another even less obvious issue with inheriting from datetime classes: see issue bpo-5516.

      Therefore, it looks like there are only two choices:

      1. Replicate all functionality in both _datetime.c and datetime.py and thus double the cost of implementing new features in CPython. (OK, maybe not double because Python development is easier than C, but increase instead of decrease.)

      2. Incur a performance penalty in every method because every C call wil have to be wrapped in Python.

      Another -1 from me.

    9. briancurtin commented on Jun 7, 2010

      @briancurtin
      MemberAuthor

      It seems like this might not be worth it or a good idea, and I have no strong feeling for this being done. Feel free to close/reject this one.

    10. abalkin commented on Jun 8, 2010

      @abalkin
      Member

      Brett Cannon wrote in a comment (msg106498) on another issue:

      """
      The stated long-term goal of the stdlib is to minimize the C extension modules to only those that have to be written in C (modules can still have performance enhancing extension back-ends). Since datetime does not meet that requirement it's not a matter of "if" but "when" datetime will get a pure Python version and use the extension code only for performance.
      """

      I'll keep this open for a while to give Brett and others a chance to respond to opposition.

    11. added
      type-featureA feature request or enhancement
      and removed
      type-bugAn unexpected behavior, bug, or error
      on Jun 8, 2010
    12. abalkin commented on Jun 8, 2010

      @abalkin
      Member

      Also, my opposition is only to splitting datetime. While I am not against splitting the time module, I believe it should be phased out eventually and posix compatibility portion folded into posix module.

    13. brettcannon commented on Jun 8, 2010

      @brettcannon
      Member

      So I see a couple of objections here to the idea that I will try to address.

      First is MAL's thinking that this will undo any C code, which it won't. The idea is that stdlib modules that do not inherently rely on other C code (e.g. sqlite3 does not fall underneath this) would have a pure Python implementation with possible C enhancements. In the case of datetime that code is done, so it won't go anywhere. In this case it would be bringing in a pure Python implementation like the one PyPy maintains. You can look at heapq if you want an existing example of what it looks like to maintain a pure Python and C version of a module.

      Alexander is worried about performance because of Python shims and duplication of work. For the performance issue, there is none. If you look at something like heapq you will see that there is an import * in there to pull in all extension code; there is no Python shim to pass through if you don't engineer the extension that way. So in datetime's case all of the extension code would just get pulled into datetime.py directly and not have any indirection cost.

      As for duplication of work, we already have that with datetime in the other Python VMs. IronPython, Jython, and PyPy have to do their own version of datetime because the stdlib doesn't provide a pure Python version for them to use. So while CPython might not be duplicating work, other people are. Besides, people typically prototype in Python anyway (including you, Alexander, for the UTC patch) and then write the C code, so there really isn't any wasted development cycles by having the Python and C version already.

      The key thing to remember is that this is so the VMs other than CPython are not treated as second-class. They are legit implementations just like CPython, but because we have this legacy stuff written in C in the stdlib they are put at a disadvantage. It would be better to pool resources and make sure everyone gets to use an equivalent standard library when possible.

      And I should also mention I expect the PyPy folks to be the ones to move their code over; I would never expect anyone to re-implement datetime from scratch.

    14. 75 remaining items

    15. changed the title [-]Add pure Python implementation of datetime module to CPython[/-] [+]Add pure Python implementation of datetime module to CPython[/+] on Jul 2, 2010
    16. abalkin commented on Jul 2, 2010

      @abalkin
      Member

      I am attaching a patch from bpo-5288 as an example of a change that I would favor more than bpo-7989-cmp.diff. This patch eliminates _utcoffset and _dst methods that duplicate utcoffset and dst, but return integer minutes rather than a timedelta.

      I am not checking these changes in sandbox because these are examples of how I plan to improve C implementation when datetime.py makes it into the main tree. I envision such changes to be discussed within context of datetime.py and if approved, implemented in C and committed simultaneously.

      Improving datetime.py implementation and making it diverge from C implementation defeats the purpose I see in having datetime.py in the first place.

      Antoine?

    17. tim-one commented on Jul 5, 2010

      @tim-one
      Member

      ...
      Another is tzinfo attribute of time. With time t,
      t.utcoffset() is kid of useless given that you
      cannot subtract it from t

      Sure you can - but you have to write your code to do time arithmetic. The time implementation does so under the covers when two "aware" time objects are compared:

      If both [time] comparands are aware and have
      different tzinfo members, the comparands are
      first adjusted by subtracting their UTC
      offsets (obtained from self.utcoffset()).
      

      and unless tzinfo is a fixed offset timezone, there
      is not enough information in t to compute the offset
      to begin with.

      The docs _suggest_ that tzinfo.utcoffset(x, None) return the "standard" UTC offset, but in the end it's up to the tzinfo subclass designer to decide what they want an aware time object to return as an offset.

      Do you have any historical insight on this one?

      History has nothing to do with it ;-) There are several uses spelled out in the docs. In addition to "aware" time comparison (mentioned above):

      • Maintaining the datetime invariant

        d == datetime.combine(d.date(), d.timetz())

      requires that an "aware" datetime's tzinfo member be attached to at least one of the date and time projections, and since raw dates are always "naive", that leaves the time projection as the only choice.

      • Various string format operations use an "aware" time object's tzinfo member to incorporate time zone information - at least time.isoformat() and time.strftime().

      That said, would have been fine by me if the "naive" versus "aware" distinction had been limited to datetime objects (i.e., if plain date and plain time objects had no notion of time zone). If you need to know why time objects "really" support being aware, you'll have to ask Guido ;-)

    18. abalkin commented on Jul 9, 2010

      @abalkin
      Member

      issue7989a.diff is a partial success implementing Nick Coghlan's testing idea. Unfortunately, datetime implementation with it's circular dependency on _strftime is not very robust with respect to import trickery.

      I am calling this a partial success because although running Lib/test/test_datetime.py does not report any errors, it only works with pure python version of pickle. (I had to add sys.modules['_pickle'] = None at the top of the module to make it work.)

      Also, the resulting test_datetime is quite an abomination!

    19. abalkin commented on Jul 13, 2010

      @abalkin
      Member

      issue9206b.diff fixes test_datetime in issue9206a.diff by restoring sys.modules in-place in tearDown method.

      Based on python-dev discussion, I am marking this as accepted and uploading the patch to Rietveld for commit review.

      Please comment on the code at http://codereview.appspot.com/1824041 . Unfortunately upload tool does not recognize copied/moved files.

    20. abalkin commented on Jul 14, 2010

      @abalkin
      Member

      In issue7989c.diff, I reverted to lazy import of _strptime, added cleanup of _xyz helper functions, and made test_datetime more robust by restoring sys.modules more thoroughly.

      Unfortunately I've encountered an issue with Rietveld that prevents me from uploading the latest patch for review. See http://code.google.com/p/rietveld/issues/detail?id=208

    21. abalkin commented on Jul 21, 2010

      @abalkin
      Member

      Is anyone interested in giving this a final review? I would like to check this in unless someone objects or needs time to review.

    22. amauryfa commented on Jul 21, 2010

      @amauryfa
      Contributor

      Technically, since the C module is now named _datetime, it needs to be renamed in Modules/Setup.dist, and most importantly in PC/config.c (because on Windows datetime is built in the main interpreter)

    23. abalkin commented on Jul 22, 2010

      @abalkin
      Member

      [datetime.c] needs to be renamed in Modules/Setup.dist, and most
      importantly in PC/config.c

      Fixed in issue7989d.diff, thanks.

      In order to commit this patch I need an SVN advise. I would like to copy datetime.py from sandbox to py3k in a way that will preserve the history. (I know, this strictly necessary, but I don't want my name on every line in svn blame datetime.py given how little I had to change there.)

      I tried both svn copy oldpath newpath and svn copy oldurl newpath and it did not work (most likely because sandbox and py3k are independent checkouts.) I don't want to use svn copy oldurl newurl because that would require a separate commit for datetime.py.

    24. abalkin commented on Jul 22, 2010

      @abalkin
      Member

      s/strictly necessary/not strictly necessary/

    25. briancurtin commented on Jul 23, 2010

      @briancurtin
      MemberAuthor

      One additional change was needed to compile on Windows:
      Index: PC/config.c
      ===================================================================

      --- PC/config.c (revision 83087)
      +++ PC/config.c (working copy)
      @@ -116,7 +116,7 @@
           {"parser", PyInit_parser},
           {"winreg", PyInit_winreg},
           {"_struct", PyInit__struct},
      -    {"datetime", PyInit_datetime},
      +    {"_datetime", PyInit__datetime},
           {"_functools", PyInit__functools},
           {"_json", PyInit__json},
    26. abalkin commented on Jul 23, 2010

      @abalkin
      Member

      Brian, thanks for the fix and for testing. I am attaching a commit-ready patch issue7989e.diff, that includes Brian's fix and a few white-space changes.

      I hope I've resolved the SVN issue: I was working in a read-only checkout while sandbox checkout was read/write.

      Here is the svn status now:

      M PCbuild/pythoncore.vcproj
      M setup.py
      M Misc/NEWS
      M PC/config.c
      A + Lib/datetime.py
      A + Lib/test/datetimetester.py
      M Lib/test/test_datetime.py
      A + Modules/_datetimemodule.c
      D Modules/datetimemodule.c
      M Modules/Setup.dist

      Note that unlike previous patches, issue7989e.diff, contains only datetime.py differences compared to sandbox. You should do

      svn cp svn+ssh://pythondev@svn.python.org/sandbox/branches/py3k-datetime/datetime.py Lib

      before it can be applied. Depending on your patch utility, you may also need to do

      svn cp Lib/test/test_datetime.py Lib/test/datetimetester.py

      I am running final tests and will commit this patch shortly.

    27. abalkin commented on Jul 23, 2010

      @abalkin
      Member

      Committed in r83112.

    28. transferred this issue fromon Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions