wrye-bash / wrye-bash

A swiss army knife for modding Bethesda games.
https://wrye-bash.github.io
GNU General Public License v3.0
455 stars 79 forks source link

Python 3 Upgrade #460

Closed Infernio closed 2 years ago

Infernio commented 4 years ago

Goold old Python 2 is dead in about 3 months as of the time of writing.

What follows is a list of roadblocks:

Things that are not roadblocks:

Useful tracking regexes (make sure to enable *.py mask):

Some resources:

Added to 308, may be addressed sooner - there's lots of factors at play here. There is also no way that I caught every issue we'll encounter on the road to py3. Supersedes: #194 and #404 Follow-ups: #55

Utumno commented 3 years ago

It would at the moment unfortunately due to getattr war and 480-pt3 branches - I intend to use from future import unicode_litterals there to reduce the diff

On Tue, Jan 12, 2021, 1:26 AM Lojack notifications@github.com wrote:

Quick question: how disruptive would it be to go ahead and prefix all the strings in brec and games? Dunno how much conflict resolution that would cause.

β€” You are receiving this because you were assigned. Reply to this email directly, view it on GitHub https://github.com/wrye-bash/wrye-bash/issues/460#issuecomment-758288248, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAKNIV5A7YTHURFDWDZJU4LSZOCIXANCNFSM4IVAKWCA .

lojack5 commented 3 years ago

Ok, will just wait then. Itching for the py3 upgrade.

Infernio commented 3 years ago

@wrye-bash/bashers I did another test run of wrye-bash/2to3 based on the latest nightly. The results are on xxx-inf-py3.

Notes from this run:

Infernio commented 3 years ago

I'll try to tackle a few of the lower-hanging ones in there today, unless someone is faster than me :P

Utumno commented 3 years ago

Haha won't be faster than you - in the parsers if you can extract a method like I said here 23e53e66c114f67817f27d954816180ccf96bafe

Infernio commented 3 years ago

First round of changes/fixups done, 2to3 result is now much cleaner (also at <800 lines worth of changes).

Utumno commented 3 years ago

Thanks Inf - forget about _key_sort will do (conflicts with as yet unmerged code)

Infernio commented 3 years ago

Full log of 2to3 output is here: https://gist.github.com/Infernio/6cc3517ed869baf1615c36d3e61776ff Only interesting bit is this:

RefactoringTool: Warnings/messages while refactoring:
RefactoringTool: ### In file /mnt/e/Infernio/Desktop/Programming/wrye-bash/Mopy/bash/bosh/_saves.py ###
RefactoringTool: Line 98: You should use 'operator.mul(('=Ib', 5), num)' here.
RefactoringTool: Line 108: You should use 'operator.mul(('=Bf', 5), num)' here.

Lines in question:

self.factions = list(starmap(_unpack, repeat(('=Ib', 5), num)))
# ...
self.modifiers = list(starmap(_unpack, repeat(('=Bf', 5), num)))

No idea what that's about, I've never even heard of starmap πŸ˜… The name is very cool though :P

Infernio commented 3 years ago

Another surprise: 2to3 does not replace __unicode__ with __str__. I'll add it to our 2to3 fork.

Edit: on a happy note, though:

localize.py   83 setup_locale: No translation file for language 'en-GB', falling back to English
localize.py   86 setup_locale: Set wx locale to 'en' (en_GB)
localize.py   95 setup_locale: Set Wrye Bash locale to 'English'
pdfviewer using PyMuPDF (GPL)
bash.py  231 dump_environment: Using Wrye Bash Version 308
bash.py  231 dump_environment: OS info: Windows-10-10.0.19041-SP0, running on Intel64 Family 6 Model 94 Stepping 3, GenuineIntel
bash.py  231 dump_environment: Python version: 3.9.1 (tags/v3.9.1:1e5d33e, Dec  7 2020, 17:08:21) [MSC v.1927 64 bit (AMD64)]
bash.py  231 dump_environment: wxPython version: 4.1.1 msw (phoenix) wxWidgets 3.1.5
bash.py  231 dump_environment: python-lz4 version: 3.1.3; bundled LZ4 version: 1.9.3
bash.py  231 dump_environment: pyyaml version: 5.4
bash.py  231 dump_environment: Input encoding: utf-8; output encoding: utf-8
bash.py  231 dump_environment: Filesystem encoding: utf-8

I've gotten to the point where the game selection shows properly :)

Infernio commented 3 years ago

As of d4aa8bf4ca763b8dc6a4e2bbb2d605fd700322b6, tests work on py3.

Some important notes from this work:

Infernio commented 3 years ago

@Utumno I'm currently going through the StringIO usages, will probably return to work on more 2to3 fixers after that.

Infernio commented 3 years ago

Nice, the StringIO from io actually has the same behavior as the py3 one:

PS C:\Users\Infernio> py -2
Python 2.7.18 (v2.7.18:8d21aa21f2, Apr 20 2020, 13:25:05) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import StringIO
>>> import io
>>> a = StringIO.StringIO()
>>> b = io.StringIO()
>>> a.write(u'foo')
>>> b.write(u'foo')
3L
>>> a.write(b'foo')
>>> b.write(b'foo')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unicode argument expected, got 'str'

That should really help catch wrong usages.

Infernio commented 3 years ago

image

It's running πŸŽ‰ Granted, all my settings don't work and the tabs are in the wrong order :P

Utumno commented 3 years ago

WOW

Yep settings backwards and forward and up and down compat...

Edit:

RefactoringTool: Line 98: You should use 'operator.mul(('=Ib', 5), num)' here.

False positive https://stackoverflow.com/a/43630024/281545

Infernio commented 3 years ago

I just built the first py3 Bashed Patch πŸŽ‰

It was an empty BP in FO3, but still :P

Utumno commented 3 years ago

rebasing

Utumno commented 3 years ago

Took all day - had to redo 27e65c64535a9b16d62208771c3863b6c55fe720 and al - I rebased your streak of insta-classic commits up till here d8c9caa629a5d772cfce03dbee7d4f2f6fb65d67 - dev ready not even much squashing needed (addressed some of the issues - diff with old nightly head). Will have to review rest of nightly

Infernio commented 3 years ago

Thanks :) Still can't believe we're this close to getting it to run πŸ˜…

Edit: I went to pull your changes to dev in, and git gc'd in the background - took ~5 minutes. Turns out my .git folder had grown to ~300MB :P

lojack5 commented 3 years ago

Tuple parameter unpacking we only use in lambdas, and 2to3 handles that so I marked it as complete (unless we don't for some reason plan on running that fixer?)

Infernio commented 3 years ago

I thought we'd gotten rid of it completely as of one of @Utumno's commits?

Edit: the reason the point was there is that the code 2to3 generates for it is incredibly ugly. See e.g. 1f4c8336855dc2aa65c98cb516f4d3d598e1a767.

Utumno commented 3 years ago

Oh yes there should be none left - hey is the Ctrl-c shortcut working for you (copy selected infos paths to clipboard)? for me returns 3 as the code: 26379dc7e93af903feae141d56f00ed842e4d5f6

Infernio commented 3 years ago

Just tested. With that commit it does not work for me, so I reverted it locally. After doing that, it works for me. I get code 67 (which is ord(u'C')).

Utumno commented 3 years ago

Thanks Inf so that's something in my env (some autohotkey script probably) - great so will omit on next iteration

lojack5 commented 3 years ago

Gone? I must have been looking at a stale branch then.

Infernio commented 3 years ago

Easiest way to test is to run the fixer from 2to3 and check git diff afterwards.

Infernio commented 3 years ago

I reran 2to3 on xxx-inf-2to3 and started rebasing xxx-inf-py3. Nearly everything conflicts :/

Edit: done, but haven't tested it yet.

Utumno commented 3 years ago

Great job - will try and finish parsers the next few days and then 460

I don't even want to think of the rebase of 480/543 :P

Infernio commented 3 years ago

Do we need another stable py2 release, or can we do the VDATA3 upgrade (i.e. decoding all bytestring settings) on py3 in the same release?

Utumno commented 3 years ago

I'd have to think a bit about that - will do when I visit the 460 branches

On Tue, Mar 30, 2021 at 1:39 PM Infernio @.***> wrote:

Do we need another stable py2 release, or can we do the VDATA3 upgrade (i.e. decoding all bytestring settings) on py3 in the same release?

β€” You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/wrye-bash/wrye-bash/issues/460#issuecomment-810115109, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAKNIV2DWNCIAU3M7DTATFTTGGS5VANCNFSM4IVAKWCA .

Infernio commented 3 years ago

Rebased my py3 branches.

Infernio commented 3 years ago

b0b85345537e287a4add2e6647c23692b749d3c3 is done, this is the last thing I wanted to do to make 2to3 less noisy/more helpful.

Infernio commented 3 years ago

Archives handling needs work:

bain.py 1356 _refreshSource: Unable to read archive 'G:\steam\steamapps\common\Fallout3 Mods\Bash Installers\FOOK2 v1-2 Open Beta Main Files Hotfixed 20140427-4448-1-2.7z'.
Traceback (most recent call last):
  File "E:\Infernio\Desktop\Programming\wrye-bash\Mopy\bash\bosh\bain.py", line 1352, in _refreshSource
    list_archive(tempArch, _parse_archive_line)
  File "E:\Infernio\Desktop\Programming\wrye-bash\Mopy\bash\archives.py", line 174, in list_archive
    maList = __reList.match(line)
TypeError: cannot use a string pattern on a bytes-like object

Pretty sure we're calling 7z via subprocess without decoding the output...

Infernio commented 3 years ago

BAIN works now:

image

...and the first real Python 3 BP:

image

Infernio commented 3 years ago

Incredibly enough, there don't seem to be any regressions in that BP. And py3 seems to be a decent bit faster at building the BP. 54s vs 71s for that FO3 BP up there.

Infernio commented 3 years ago

@Utumno I think we should do the VDATA3 upgrade on one last stable py2 release.

Pros:

Cons:

If we do decide to do it now, we should take this opportunity to drop the __reduce__ overrides in bain.py and converters.py. They're there to make versions prior to 307 work with newer settings formats, but that's obviously pointless if we change the format version to VDATA3 anyways. That also means we'll be able to drop the hacky imports in bosh/__init__.py once we are on py3 since we'll require VDATA3 at that point.

Utumno commented 3 years ago

Let me have a closer look at VDATA3 - 309 being small is not really an issue - and we did shuffle a lot the code so yeah

On Sat, May 1, 2021, 1:57 PM Infernio @.***> wrote:

@Utumno https://github.com/Utumno I think we should do the VDATA3 upgrade on one last stable py2 release.

Pros:

  • Doing it this way definitely works and is much lower risk than trying to do both at the same time.
  • If we do it this way, we can reject anything that isn't in VDATA3 format once we're on py3 - which means we can drop every single backwards compatibility hack right then along with all py2 weirdness. Otherwise we'd need a VDATA4 for dropping backwards compatibility hacks.
  • 309 obsoletes valda's FO3/FNV versions for good, which may be an important enough reason to release a stable.

Cons:

  • Outside of the FO3/FNV change mentioned, 309 is pretty small.

If we do decide to do it now, we should take this opportunity to drop the reduce overrides in bain.py and converters.py. They're there to make versions prior to 307 work with newer settings formats, but that's obviously pointless if we change the format version to VDATA3 anyways. That also means we'll be able to drop the hacky imports in bosh/init.py once we are on py3 since we'll require VDATA3 at that point.

β€” You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/wrye-bash/wrye-bash/issues/460#issuecomment-830612666, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAKNIV54WWUBPFXOHWIIQNLTLPNBTANCNFSM4IVAKWCA .

Utumno commented 3 years ago

Otherwise we'd need a VDATA4

I am afraid we need a VDATA4 for #543 - see also __drop_paths in 6f0a5bce24999de1855fb7178af0685e4516993c (broken generally). But I don't mind a VDATA4 tbh as 543 is difficult to finalize now and getting rid of some of the cruft is a good idea anyways. Then a 309 beta with the settings changes to catch regressions and then py3 on 310 first thing?

In a7f68b5e900daeca8770a3c8751e9f134b24ea47 do not save the settings however - this should be taken care of in normal exit.

Infernio commented 3 years ago

IIRC I made it save settings because otherwise it won't convert a couple settings files because it checks if they've changed. I don't recall which ones those were, but I want to say converters and the like?

Infernio commented 3 years ago

Also, I just realized that the VDATA3 commit will break defaultdicts because it doesn't pass the factory into the constructor. Do we pickle any defaultdicts?

Utumno commented 3 years ago

Hmmm - good question - a "solution" would be to copy the dict then clear it and update from the (converted) copy

Unrelated but... do not drop ordered dicts if you thought about that - py3 ones are ordered but if order matters to us we should name accordingly - ordered_xxx - then drop (so after 460)

I discovered some regressions in parsers (from Rounder mostly) that I added on nightly. Takes a lot of cruft for the ride :)

Infernio commented 3 years ago

I'll have to do some testing. And yeah, doing anything with relying on dict insertion order needs thought wrt. naming, typing etc.

Utumno commented 3 years ago

New fixups in parsers - I am confident I caught most bugs in there now plus quite a few code gone. Intend to merge next round - seems maintenance is ongoing on your front too :P

Re: VDATA3 let's go but in a way VDATA4 (CIStr keys) is as easy as possible - needs some thought

Infernio commented 3 years ago

seems maintenance is ongoing on your front too :P

All of those were born from trying to update the mods in my SSE load order to their latest versions. Added like 10 future nice-to-haves to my TODO list too :P

Infernio commented 3 years ago

I've rebased my py3 branch. Left 68c3921c3 out because it conflicted hard and I don't really know what the code around it is doing anymore :P

Infernio commented 3 years ago

I've also done a bit of testing on VDATA3 now:

Infernio commented 3 years ago

Got a lot of py3 testing done today. Pretty much everything seems to work now πŸŽ‰ One thing to watch out for is 7c5114632d906d29eb30115b8a0cdb5e9a47c6c9 - there may be a couple more of these bound method problems hiding in the codebase.

Utumno commented 3 years ago

I've rebased my py3 branch. Left 68c3921 out because it conflicted hard and I don't really know what the code around it is doing anymore :P

No worries will get to that

I've also done a bit of testing on VDATA3 now:

Great job!

Infernio commented 3 years ago

nightly-vdata3 has the rebased VDATA3 commit.

Utumno commented 2 years ago

I'd say we bit the bullet with VDATA3 - that is have 309 out. However we shouldn't drop compatibility with VDATA2 unless well into py3 - there will be people upgrading from 308 to 310 - let's drop VDATA2 in 311?

Meanwhile parsers were broken in py3 - csv.reader is unicode now (duh) - see 1e85d6e44975d9543173aa5c46ce36b180a72dac - let me rebase a bit :)

Infernio commented 2 years ago

I don't know if doing the upgrade on py3 is possible. Maybe with encoding='bytes' and running conv_obj on it, but I'd have to test it first.

On 21. May 2021, at 11:23, Utumno @.***> wrote:

ο»Ώ I'd say we bit the bullet with VDATA3 - that is have 309 out. However we shouldn't drop compatibility with VDATA2 unless well into py3 - there will be people upgrading from 308 to 310 - let's drop VDATA2 in 311?

Meanwhile parsers were broken in py3 - csv.reader is unicode now (duh) - see 1e85d6e - let me rebase a bit :)

β€” You are receiving this because you were assigned. Reply to this email directly, view it on GitHub, or unsubscribe.