Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jdatetime and jdate objects cannot be pickled anymore in 3.8.0 #108

Closed
sinarezaei opened this issue Jan 10, 2022 · 12 comments · Fixed by #109 or #113
Closed

jdatetime and jdate objects cannot be pickled anymore in 3.8.0 #108

sinarezaei opened this issue Jan 10, 2022 · 12 comments · Fixed by #109 or #113
Labels

Comments

@sinarezaei
Copy link

sinarezaei commented Jan 10, 2022

In the latest update (3.8.0), jdatetime objects could't be pickled

import jdatetime
import pickle
pickle.dumps(jdatetime.datetime.now())

Results in the following error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Can't pickle local object 'date._strftime_replace_func.<locals>.simple_replace

In version 3.6.2 of jdatetime, it was working with no errors

  • jdatetime version: 3.8.0
  • Python version: 3.7.9
  • OS: Ubuntu
@sinarezaei sinarezaei changed the title jdatetime and jdate objects cannot be pickled anymore jdatetime and jdate objects cannot be pickled anymore IN 3.8.0 Jan 10, 2022
@sinarezaei sinarezaei changed the title jdatetime and jdate objects cannot be pickled anymore IN 3.8.0 jdatetime and jdate objects cannot be pickled anymore in 3.8.0 Jan 10, 2022
@hramezani
Copy link
Collaborator

Thanks @sinarezaei for reporting. we will investigate the problem.

@hramezani hramezani added the bug label Jan 11, 2022
@hramezani
Copy link
Collaborator

I've created a PR to fix the issue #109
Could you please test it?

@hramezani
Copy link
Collaborator

It got fixed in 3.8.1

@sinarezaei
Copy link
Author

sinarezaei commented Jan 17, 2022

I've created a PR to fix the issue #109 Could you please test it?

Checked, it's fixed in PR, Thanks a lot!

@jetX11
Copy link

jetX11 commented Jan 23, 2022

I think it still has some bug with unpickled jdatetime object. Apparently, the object (retrieved from the previous pickled file) does not work properly with f-string formatting like f'{some_jdatetime:%Y/%m/%d %H:%M:%S}' like the fresh jdatetime object:

AttributeError: 'datetime' object has no attribute '_strftime_mapping'

OK! I found what is the wrong! The object pickled (dump) by the previous version of jdatetime cannot be treated as a true jdatetime object when retrieved (load) by the new version! The object has been totally restructured.

@jetX11
Copy link

jetX11 commented Jan 23, 2022

The experiment using bash version 4.4.20 and python version 3.9.7:


bash :

# installing an old version of jdatetime
pip uninstall jdatetime
pip install -Iv jdatetime==3.7.0

pthon:

import jdatetime
import pickle

# saving a jdatetime object using pickle file foo.pickle
with open('foo.pickle', 'wb') as ofile:
    pickle.dump(jdatetime.datetime.now(), ofile)

now = jdatetime.datetime.now()
print(f'{now:%Y/%m/%d %H:%M}')
# OK! Fine! prints formatted date/time

bash:

# upgrading to new version : (3.8.1)
pip install --upgrade jdatetime

pthon:

import jdatetime
import pickle

# retrieving the previous jdatetime object:
with open('foo.pickle', 'rb') as ifile:
    then = pickle.load(ifile)

# now try to print formatted object:
print(f'{then:%Y/%m/%d %H:%M}')
# trouble!
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/XXXX/.virtualenvs/minon/lib/python3.9/site-packages/jdatetime/__init__.py", line 579, in __format__
    return self.strftime(format)
  File "/home/XXXX/.virtualenvs/minon/lib/python3.9/site-packages/jdatetime/__init__.py", line 640, in strftime
    if symbol in self._strftime_mapping:
AttributeError: 'datetime' object has no attribute '_strftime_mapping'

@hramezani
Copy link
Collaborator

I don't think that the object pickled in an old version should be unpickled in the new version.

@jetX11
Copy link

jetX11 commented Jan 23, 2022

I don't think that the object pickled in an old version should be unpickled in the new version.

Why not?! Even as a subjective opinion, it is strongly arguable.

Two basic questions:

  1. Should a program keep running with some old modules ... no matter how those modules should or could be upgraded for bug fix, better performance, new features, ...?
  2. Each time a module is upgraded, should we redesign our old programs to cope with the new module features?

Pickling is an essential feature of python for task management and persistency. I have been using hundreds of modules (including jdatetime) with a few dozen of my programs. with exception of a few nasty cases, the requirements have always typically been

jdatetime>=3.7.0
(NOT jdatetime>=3.7.0,<3,8.0)

and that is the right objective statement.

With your statement, my program will be restricted to a specific version of some modules; especially if the user of my programs have already be using it with a large set of preserved data.

Of course, we can convert the underlying timestamp of the jdatetime object each time before pickling, and after unpickling; that is, something like:

import jdatetime
import datetime


# before pickling (ts pickled):
ts = jdatetime.datetime.now().togregorian().timestamp()

# after unpickling (ts unpickled)
jdt = jdatetime.datetime.fromgregorian(datetime=datetime.datetime.fromtimestamp(ts))

But, then why we have used jdatetime for in the first place? What about its seamless integration with python ecosystem? Wasn't it supposed to be seamlessly equivalent to the standard datetime module?

Good luck

@hramezani
Copy link
Collaborator

Thanks, @jetX11 for your explanation.
I've created a PR to fix this problem.
#113

It would be great if you can confirm that this patch fixes your problem.

@jetX11
Copy link

jetX11 commented Jan 23, 2022

Thank you @hramezani for attention. OK! I'll check it. Well done.

@jetX11
Copy link

jetX11 commented Jan 24, 2022

Sorry for delay dear @hramezani ; I was expecting the patch appear as a new version of jdatetime (3.8.2)! I am new to GitHub ... as an active user (I have downloaded from it for ages).

Any way, I manually modified the file __init__.py of jdatetime version 3.8.1 (from the file changed by you here [1]) and it could unpickle the previously pickled object of version 3.7.0 without any problem! Thanks a lot.

[1] __init__.py (https://github.com/hramezani/python-jalali/blob/df234fa66eba17f37204a3a6191e8651691bde4c/jdatetime/__init__.py)

@hramezani
Copy link
Collaborator

@jetX11 Thanks for your feedback.
python-jalali 3.8.2 now is available!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
3 participants