0

Here is code snippet:

glob.glob('C:\\intelFPGA\\*')
['C:\\intelFPGA\\17.1', 'C:\\intelFPGA\\18.0', 'C:\\intelFPGA\\18.1', 'C:\\intelFPGA\\20.0', 'C:\\intelFPGA\\9.2']

I need a method that will return the path string that has the latest version number which is 18.1 in this case. Is there a built in way to do this or am I limited to doing string manipulation to achieve this i.e a custom solution?

gyuunyuu
  • 526
  • 5
  • 17

3 Answers3

2
from pathlib import Path

root = Path('C:\\intelFPGA')
latest = max(root.glob('*'), key=lambda p: float(p.name))

If you can have more parts than 2 in version, like major.minor.patch then this will not work. You can do this instead:

root = Path('C:\\intelFPGA')
latest = max(root.glob('*'), key=lambda p: tuple(map(int, p.name.split('.'))))
Cyrille Pontvieux
  • 2,356
  • 1
  • 21
  • 29
  • Yes, `[-1]` sorry. and yes `max` is better. – Cyrille Pontvieux Nov 11 '20 at 10:06
  • 2
    The float approach doesn't work with minor versions > 9 because e.g. `1.12` is sorted before `1.9`. +1 For the other solution. If anyone is curious why this works: "because tuples are compared lexicographically" as described in the [sorting howto](https://docs.python.org/3/howto/sorting.html#the-old-way-using-decorate-sort-undecorate). – danzel Nov 11 '20 at 10:16
1

here is the solution:

from sortedcontainers import SortedDict

folders = ['C:\\intelFPGA\\17.1', 'C:\\intelFPGA\\18.0', 'C:\\intelFPGA\\18.1', 'C:\\intelFPGA\\20.0', 'C:\\intelFPGA\\9.2']


data = {}

for folder in folders:
    info = folder.split("\\")
    version = float(info[-1])
    data.update({version:folder})


s = SortedDict(data)
print(s)

your result will be:

SortedDict({9.2: 'C:\\intelFPGA\\9.2', 17.1: 'C:\\intelFPGA\\17.1', 18.0: 'C:\\intelFPGA\\18.0', 18.1: 'C:\\intelFPGA\\18.1', 20.0: 'C:\\intelFPGA\\20.0'})
Jasar Orion
  • 626
  • 7
  • 26
0

You could use pathlib.Path.glob() with packaging.version.parse():

from packaging import version
from pathlib import Path 


def get_latest(folder):
    selected_path = None
    latest_version = version.parse('0')
    for item in Path(folder).glob('*'):
        if not item.is_dir():
            continue

        ver = version.parse(item.name)

        if isinstance(ver, version.LegacyVersion):
            continue # not PEP 440 compatible version

        if ver > latest_version:
            latest_version = ver
            selected_path = str(item)

    return selected_path

latest_path = get_latest(r'C:\intelFPGA')

Short explanation

  • The glob('*') iterates over all content in the folder
  • The item.is_dir() is needed to filter out everything which is not a directory
  • The isinstance(ver, version.LegacyVersion) is needed since you may have a folder there that does not match your pattern (folder name that contains other characters than numbers and dots.)
  • The packaging.version is needed for version comparison, since version.parse('1.12') > version.parse('1.5'), but float('1.12') < float('1.5'), and "1.2.3" is also a valid version name.
Niko Föhr
  • 28,336
  • 10
  • 93
  • 96
  • What if glob returns empty since no match was made? I guess we can just run a check before we enter the loop right? – gyuunyuu Nov 11 '20 at 11:12
  • Then the `get_latest()` will return `None`. You could handle this later by checking if the return value is `None` or a string pointing to the desired path. – Niko Föhr Nov 11 '20 at 11:21