Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pefile for openSUSE:Factory 
checked in at 2023-04-04 21:16:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pefile (Old)
 and      /work/SRC/openSUSE:Factory/.python-pefile.new.19717 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pefile"

Tue Apr  4 21:16:53 2023 rev:7 rq:1076772 version:2023.2.7

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pefile/python-pefile.changes      
2022-06-07 11:45:24.899253698 +0200
+++ /work/SRC/openSUSE:Factory/.python-pefile.new.19717/python-pefile.changes   
2023-04-04 21:16:54.747848472 +0200
@@ -1,0 +2,13 @@
+Sun Mar 26 19:55:48 UTC 2023 - Dirk Müller <dmuel...@suse.com>
+
+- update to 2023.2.7:
+  * accept dot in valid charset for name
+  * Remove future from dependencies
+  * Add machine types
+  * Incorporate PEP 238 and PEP 3120
+  * Generate GUID fields of CV_INFO_PDB70 readable by Python
+  * Dynamic relocations support
+  * Add Export Hash Method
+  * Loosen export symbol validation
+
+-------------------------------------------------------------------

Old:
----
  pefile-2022.5.30.tar.gz

New:
----
  pefile-2023.2.7.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pefile.spec ++++++
--- /var/tmp/diff_new_pack.BF2zup/_old  2023-04-04 21:16:55.855855536 +0200
+++ /var/tmp/diff_new_pack.BF2zup/_new  2023-04-04 21:16:55.863855587 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-pefile
 #
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -20,7 +20,7 @@
 %define skip_python2 1
 
 Name:           python-pefile
-Version:        2022.5.30
+Version:        2023.2.7
 Release:        0
 Summary:        A python module to work with PE (pertable executable) files
 License:        BSD-3-Clause
@@ -30,10 +30,6 @@
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
-Requires:       python-future
-# SECTION test requirements
-BuildRequires:  %{python_module future}
-# /SECTION
 BuildArch:      noarch
 
 %python_subpackages

++++++ pefile-2022.5.30.tar.gz -> pefile-2023.2.7.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pefile-2022.5.30/.gitignore 
new/pefile-2023.2.7/.gitignore
--- old/pefile-2022.5.30/.gitignore     2021-09-03 16:11:44.000000000 +0200
+++ new/pefile-2023.2.7/.gitignore      2023-01-07 20:42:11.000000000 +0100
@@ -21,3 +21,7 @@
 /dist
 /pefile.egg-info
 .DS_Store
+pefile.code-workspace
+.vscode/*
+pefile.ipynb
+.ipynb_checkpoints/*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pefile-2022.5.30/.travis.yml 
new/pefile-2023.2.7/.travis.yml
--- old/pefile-2022.5.30/.travis.yml    2021-05-13 20:15:20.000000000 +0200
+++ new/pefile-2023.2.7/.travis.yml     1970-01-01 01:00:00.000000000 +0100
@@ -1,34 +0,0 @@
-language: python3
-cache: pip3
-matrix:
-  include:
-    - python: 3.8
-    - python: 3.9
-      dist: xenial
-    - python: nightly
-      dist: xenial
-    - python: pypy3
-before_install:
-- if test -n "$encrypted_b0257fbf4222_key" && test -n 
"$encrypted_b0257fbf4222_iv"; then
-    openssl aes-256-cbc -K $encrypted_b0257fbf4222_key -iv 
$encrypted_b0257fbf4222_iv -in tests/test_data.tar.bz2.enc -out 
tests/test_data.tar.bz2 -d;
-    tar jxf tests/test_data.tar.bz2 -C tests;
-  fi
-install:
-- pip install -U pip pytest-cov codecov
-- pip install -I -e .
-script:
-- chmod +x ./run_tests.py ./setup.py
-- python setup.py test
-- python setup.py build
-- python setup.py sdist
-- python setup.py bdist
-- python setup.py install
-- coverage run --source=pefile --omit="*_test*,*__init__*,*test_lib*" 
./run_tests.py
-after_success:
-- coveralls --verbose
-addons:
-  artifacts:
-    debug: true
-    paths:
-    - $(git ls-files -o | grep .txt | grep -v pefile.egg-info | tr "\n" ":")
-    - codecov
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pefile-2022.5.30/LICENSE new/pefile-2023.2.7/LICENSE
--- old/pefile-2022.5.30/LICENSE        2022-05-30 15:25:22.000000000 +0200
+++ new/pefile-2023.2.7/LICENSE 2023-01-07 20:12:32.000000000 +0100
@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2004-2022 Ero Carrera
+Copyright (c) 2004-2023 Ero Carrera
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pefile-2022.5.30/PKG-INFO 
new/pefile-2023.2.7/PKG-INFO
--- old/pefile-2022.5.30/PKG-INFO       2022-05-30 16:07:24.178253700 +0200
+++ new/pefile-2023.2.7/PKG-INFO        2023-02-07 13:19:22.005508400 +0100
@@ -1,9 +1,9 @@
 Metadata-Version: 2.1
 Name: pefile
-Version: 2022.5.30
+Version: 2023.2.7
 Summary: Python PE parsing module
 Home-page: https://github.com/erocarrera/pefile
-Download-URL: 
https://github.com/erocarrera/pefile/releases/download/v2022.5.30/pefile-2022.5.30.tar.gz
+Download-URL: 
https://github.com/erocarrera/pefile/releases/download/v2023.2.7/pefile-2023.2.7.tar.gz
 Author: Ero Carrera
 Author-email: ero.carr...@gmail.com
 License: MIT
@@ -31,4 +31,4 @@
 standard use. To the best of my knowledge most of the abuse is handled
 gracefully.
 
-Copyright (c) 2005-2022 Ero Carrera <ero.carr...@gmail.com>
+Copyright (c) 2005-2023 Ero Carrera <ero.carr...@gmail.com>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pefile-2022.5.30/ordlookup/__init__.py 
new/pefile-2023.2.7/ordlookup/__init__.py
--- old/pefile-2022.5.30/ordlookup/__init__.py  2021-09-03 16:05:28.000000000 
+0200
+++ new/pefile-2023.2.7/ordlookup/__init__.py   2023-01-07 20:14:04.000000000 
+0100
@@ -1,5 +1,3 @@
-from __future__ import absolute_import
-import sys
 from . import ws2_32
 from . import oleaut32
 
@@ -15,18 +13,9 @@
     b"oleaut32.dll": oleaut32.ord_names,
 }
 
-PY3 = sys.version_info > (3,)
 
-if PY3:
-
-    def formatOrdString(ord_val):
-        return "ord{}".format(ord_val).encode()
-
-
-else:
-
-    def formatOrdString(ord_val):
-        return b"ord%d" % ord_val
+def formatOrdString(ord_val):
+    return "ord{}".format(ord_val).encode()
 
 
 def ordLookup(libname, ord_val, make_name=False):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pefile-2022.5.30/pefile.egg-info/PKG-INFO 
new/pefile-2023.2.7/pefile.egg-info/PKG-INFO
--- old/pefile-2022.5.30/pefile.egg-info/PKG-INFO       2022-05-30 
16:07:23.000000000 +0200
+++ new/pefile-2023.2.7/pefile.egg-info/PKG-INFO        2023-02-07 
13:19:21.000000000 +0100
@@ -1,9 +1,9 @@
 Metadata-Version: 2.1
 Name: pefile
-Version: 2022.5.30
+Version: 2023.2.7
 Summary: Python PE parsing module
 Home-page: https://github.com/erocarrera/pefile
-Download-URL: 
https://github.com/erocarrera/pefile/releases/download/v2022.5.30/pefile-2022.5.30.tar.gz
+Download-URL: 
https://github.com/erocarrera/pefile/releases/download/v2023.2.7/pefile-2023.2.7.tar.gz
 Author: Ero Carrera
 Author-email: ero.carr...@gmail.com
 License: MIT
@@ -31,4 +31,4 @@
 standard use. To the best of my knowledge most of the abuse is handled
 gracefully.
 
-Copyright (c) 2005-2022 Ero Carrera <ero.carr...@gmail.com>
+Copyright (c) 2005-2023 Ero Carrera <ero.carr...@gmail.com>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pefile-2022.5.30/pefile.egg-info/SOURCES.txt 
new/pefile-2023.2.7/pefile.egg-info/SOURCES.txt
--- old/pefile-2022.5.30/pefile.egg-info/SOURCES.txt    2022-05-30 
16:07:23.000000000 +0200
+++ new/pefile-2023.2.7/pefile.egg-info/SOURCES.txt     2023-02-07 
13:19:21.000000000 +0100
@@ -1,5 +1,4 @@
 .gitignore
-.travis.yml
 LICENSE
 MANIFEST.in
 README
@@ -13,5 +12,4 @@
 pefile.egg-info/PKG-INFO
 pefile.egg-info/SOURCES.txt
 pefile.egg-info/dependency_links.txt
-pefile.egg-info/requires.txt
 pefile.egg-info/top_level.txt
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pefile-2022.5.30/pefile.egg-info/requires.txt 
new/pefile-2023.2.7/pefile.egg-info/requires.txt
--- old/pefile-2022.5.30/pefile.egg-info/requires.txt   2022-05-30 
16:07:23.000000000 +0200
+++ new/pefile-2023.2.7/pefile.egg-info/requires.txt    1970-01-01 
01:00:00.000000000 +0100
@@ -1 +0,0 @@
-future
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pefile-2022.5.30/pefile.py 
new/pefile-2023.2.7/pefile.py
--- old/pefile-2022.5.30/pefile.py      2022-05-30 15:25:27.000000000 +0200
+++ new/pefile-2023.2.7/pefile.py       2023-02-06 23:43:49.000000000 +0100
@@ -1,5 +1,5 @@
 #!/usr/bin/python
-# -*- coding: utf-8 -*-
+
 """pefile, Portable Executable reader module
 
 All the PE file basic structures are available with their default names as
@@ -13,11 +13,11 @@
 standard use. To the best of my knowledge most of the abuse is handled
 gracefully.
 
-Copyright (c) 2005-2022 Ero Carrera <ero.carr...@gmail.com>
+Copyright (c) 2005-2023 Ero Carrera <ero.carr...@gmail.com>
 """
 
 __author__ = "Ero Carrera"
-__version__ = "2022.5.30"
+__version__ = "2023.2.7"
 __contact__ = "ero.carr...@gmail.com"
 
 import collections
@@ -28,8 +28,10 @@
 import math
 import string
 import mmap
+import uuid
 
 from collections import Counter
+from typing import Union
 from hashlib import sha1
 from hashlib import sha256
 from hashlib import sha512
@@ -106,7 +108,7 @@
 MAX_DLL_LENGTH = 0x200
 MAX_SYMBOL_NAME_LENGTH = 0x200
 
-# Lmit maximum number of sections before processing of sections will stop
+# Limit maximum number of sections before processing of sections will stop
 MAX_SECTIONS = 0x800
 
 # The global maximum number of resource entries to parse per file
@@ -278,7 +280,7 @@
 
 
 machine_types = [
-    ("IMAGE_FILE_MACHINE_UNKNOWN", 0),
+    ("IMAGE_FILE_MACHINE_UNKNOWN", 0x0),
     ("IMAGE_FILE_MACHINE_I386", 0x014C),
     ("IMAGE_FILE_MACHINE_R3000", 0x0162),
     ("IMAGE_FILE_MACHINE_R4000", 0x0166),
@@ -305,6 +307,11 @@
     ("IMAGE_FILE_MACHINE_TRICORE", 0x0520),
     ("IMAGE_FILE_MACHINE_CEF", 0x0CEF),
     ("IMAGE_FILE_MACHINE_EBC", 0x0EBC),
+    ("IMAGE_FILE_MACHINE_RISCV32", 0x5032),
+    ("IMAGE_FILE_MACHINE_RISCV64", 0x5064),
+    ("IMAGE_FILE_MACHINE_RISCV128", 0x5128),
+    ("IMAGE_FILE_MACHINE_LOONGARCH32", 0x6232),
+    ("IMAGE_FILE_MACHINE_LOONGARCH64", 0x6264),
     ("IMAGE_FILE_MACHINE_AMD64", 0x8664),
     ("IMAGE_FILE_MACHINE_M32R", 0x9041),
     ("IMAGE_FILE_MACHINE_ARM64", 0xAA64),
@@ -900,7 +907,7 @@
 @lru_cache(maxsize=2048, copy=True)
 def set_format(format):
 
-    __format__ = "<"
+    __format_str__ = "<"
     __unpacked_data_elms__ = []
     __field_offsets__ = {}
     __keys__ = []
@@ -910,7 +917,7 @@
     for elm in format:
         if "," in elm:
             elm_type, elm_name = elm.split(",", 1)
-            __format__ += elm_type
+            __format_str__ += elm_type
             __unpacked_data_elms__.append(None)
 
             elm_names = elm_name.split(",")
@@ -930,10 +937,10 @@
             # all the possible members referring to the data.
             __keys__.append(names)
 
-    __format_length__ = struct.calcsize(__format__)
+    __format_length__ = struct.calcsize(__format_str__)
 
     return (
-        __format__,
+        __format_str__,
         __unpacked_data_elms__,
         __field_offsets__,
         __keys__,
@@ -950,7 +957,7 @@
 
     def __init__(self, format, name=None, file_offset=None):
         # Format is forced little endian, for big endian non Intel platforms
-        self.__format__ = "<"
+        self.__format_str__ = "<"
         self.__keys__ = []
         self.__format_length__ = 0
         self.__field_offsets__ = {}
@@ -962,7 +969,7 @@
             d = tuple(d)
 
         (
-            self.__format__,
+            self.__format_str__,
             self.__unpacked_data_elms__,
             self.__field_offsets__,
             self.__keys__,
@@ -976,8 +983,8 @@
         else:
             self.name = format[0]
 
-    def __get_format__(self):
-        return self.__format__
+    def __get_format__(self) -> str:
+        return self.__format_str__
 
     def get_field_absolute_offset(self, field_name):
         """Return the offset within the field for the requested field in the 
structure."""
@@ -1021,7 +1028,7 @@
         if count_zeroes(data) == len(data):
             self.__all_zeroes__ = True
 
-        self.__unpacked_data_elms__ = struct.unpack(self.__format__, data)
+        self.__unpacked_data_elms__ = struct.unpack(self.__format_str__, data)
         for idx, val in enumerate(self.__unpacked_data_elms__):
             for key in self.__keys__[idx]:
                 setattr(self, key, val)
@@ -1031,18 +1038,16 @@
         new_values = []
 
         for idx, val in enumerate(self.__unpacked_data_elms__):
-
+            new_val = None
             for key in self.__keys__[idx]:
                 new_val = getattr(self, key)
-
                 # In the case of unions, when the first changed value
                 # is picked the loop is exited
                 if new_val != val:
                     break
-
             new_values.append(new_val)
 
-        return struct.pack(self.__format__, *new_values)
+        return struct.pack(self.__format_str__, *new_values)
 
     def __str__(self):
         return "\n".join(self.dump())
@@ -1152,6 +1157,10 @@
             self.pe = argd["pe"]
             del argd["pe"]
 
+        self.PointerToRawData = None
+        self.VirtualAddress = None
+        self.SizeOfRawData = None
+        self.Misc_VirtualSize = None
         Structure.__init__(self, *argl, **argd)
         self.PointerToRawData_adj = None
         self.VirtualAddress_adj = None
@@ -1204,17 +1213,20 @@
 
         if length is not None:
             end = offset + length
-        else:
+        elif self.SizeOfRawData is not None:
             end = offset + self.SizeOfRawData
+        else:
+            end = offset
 
-        if ignore_padding:
+        if ignore_padding and end is not None and offset is not None:
             end = min(end, offset + self.Misc_VirtualSize)
 
         # PointerToRawData is not adjusted here as we might want to read any 
possible
         # extra bytes that might get cut off by aligning the start (and hence 
cutting
         # something off the end)
-        if end > self.PointerToRawData + self.SizeOfRawData:
-            end = self.PointerToRawData + self.SizeOfRawData
+        if self.PointerToRawData is not None and self.SizeOfRawData is not 
None:
+            if end > self.PointerToRawData + self.SizeOfRawData:
+                end = self.PointerToRawData + self.SizeOfRawData
         return self.pe.__data__[offset:end]
 
     def __setattr__(self, name, val):
@@ -1447,7 +1459,7 @@
 
     def __init__(self, format, name=None, file_offset=None):
         (
-            self.__format__,
+            self.__format_str__,
             self.__format_length__,
             self.__field_offsets__,
             self.__keys__,
@@ -1713,6 +1725,15 @@
     """
 
 
+class DynamicRelocationData(DataContainer):
+    """Holds dynamic relocation information.
+
+    struct:        IMAGE_DYNAMIC_RELOCATION structure
+    symbol:        Symbol to which dynamic relocations must be applied
+    relocations:   List of dynamic relocations for this symbol 
(BaseRelocationData instances)
+    """
+
+
 class BaseRelocationData(DataContainer):
     """Holds base relocation information.
 
@@ -1785,6 +1806,7 @@
 
     struct:     IMAGE_LOAD_CONFIG_DIRECTORY structure
     name:       dll name
+    dynamic_relocations: dynamic relocation information, if present
     """
 
 
@@ -2277,18 +2299,25 @@
 # Check if an imported name uses the valid accepted characters expected in
 # mangled function names. If the symbol's characters don't fall within this
 # charset we will assume the name is invalid.
-
+# The dot "." character comes from: 
https://github.com/erocarrera/pefile/pull/346
+# All other symbols can be inserted by adding a name with that symbol to a 
.def file,
+# and passing it to link.exe (See export_test.py)
 allowed_function_name = b(
-    string.ascii_lowercase + string.ascii_uppercase + string.digits + 
"_?@$()<>"
+    string.ascii_lowercase + string.ascii_uppercase + string.digits
 )
 
 
 @lru_cache(maxsize=2048)
-def is_valid_function_name(s):
+def is_valid_function_name(
+    s: Union[str, bytes, bytearray], relax_allowed_characters: bool = False
+) -> bool:
+    allowed_extra = b"._?@$()<>"
+    if relax_allowed_characters:
+        allowed_extra = b"!\"#$%&'()*+,-./:<>?[\\]^_`{|}~@"
     return (
         s is not None
         and isinstance(s, (str, bytes, bytearray))
-        and all(c in allowed_function_name for c in set(s))
+        and all((c in allowed_function_name or c in allowed_extra) for c in 
set(s))
     )
 
 
@@ -2630,6 +2659,27 @@
         ("H,Data",),
     )
 
+    __IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION_format__ = (
+        "IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION",
+        ("I:12,PageRelativeOffset", "I:1,IndirectCall", "I:19,IATIndex"),
+    )
+
+    __IMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION_format__ = (
+        "IMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION",
+        (
+            "I:12,PageRelativeOffset",
+            "I:1,IndirectCall",
+            "I:1,RexWPrefix",
+            "I:1,CfgCheck",
+            "I:1,Reserved",
+        ),
+    )
+
+    __IMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION_format__ = (
+        "IMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION",
+        ("I:12,PageRelativeOffset", "I:4,RegisterNumber"),
+    )
+
     __IMAGE_TLS_DIRECTORY_format__ = (
         "IMAGE_TLS_DIRECTORY",
         (
@@ -2678,10 +2728,28 @@
             "I,SEHandlerTable",
             "I,SEHandlerCount",
             "I,GuardCFCheckFunctionPointer",
-            "I,Reserved2",
+            "I,GuardCFDispatchFunctionPointer",
             "I,GuardCFFunctionTable",
             "I,GuardCFFunctionCount",
             "I,GuardFlags",
+            "H,CodeIntegrityFlags",
+            "H,CodeIntegrityCatalog",
+            "I,CodeIntegrityCatalogOffset",
+            "I,CodeIntegrityReserved",
+            "I,GuardAddressTakenIatEntryTable",
+            "I,GuardAddressTakenIatEntryCount",
+            "I,GuardLongJumpTargetTable",
+            "I,GuardLongJumpTargetCount",
+            "I,DynamicValueRelocTable",
+            "I,CHPEMetadataPointer",
+            "I,GuardRFFailureRoutine",
+            "I,GuardRFFailureRoutineFunctionPointer",
+            "I,DynamicValueRelocTableOffset",
+            "H,DynamicValueRelocTableSection",
+            "H,Reserved2",
+            "I,GuardRFVerifyStackPointerFunctionPointer" 
"I,HotPatchTableOffset",
+            "I,Reserved3",
+            "I,EnclaveConfigurationPointer",
         ),
     )
 
@@ -2709,13 +2777,57 @@
             "Q,SEHandlerTable",
             "Q,SEHandlerCount",
             "Q,GuardCFCheckFunctionPointer",
-            "Q,Reserved2",
+            "Q,GuardCFDispatchFunctionPointer",
             "Q,GuardCFFunctionTable",
             "Q,GuardCFFunctionCount",
             "I,GuardFlags",
+            "H,CodeIntegrityFlags",
+            "H,CodeIntegrityCatalog",
+            "I,CodeIntegrityCatalogOffset",
+            "I,CodeIntegrityReserved",
+            "Q,GuardAddressTakenIatEntryTable",
+            "Q,GuardAddressTakenIatEntryCount",
+            "Q,GuardLongJumpTargetTable",
+            "Q,GuardLongJumpTargetCount",
+            "Q,DynamicValueRelocTable",
+            "Q,CHPEMetadataPointer",
+            "Q,GuardRFFailureRoutine",
+            "Q,GuardRFFailureRoutineFunctionPointer",
+            "I,DynamicValueRelocTableOffset",
+            "H,DynamicValueRelocTableSection",
+            "H,Reserved2",
+            "Q,GuardRFVerifyStackPointerFunctionPointer",
+            "I,HotPatchTableOffset",
+            "I,Reserved3",
+            "Q,EnclaveConfigurationPointer",
         ),
     )
 
+    __IMAGE_DYNAMIC_RELOCATION_TABLE_format__ = (
+        "IMAGE_DYNAMIC_RELOCATION_TABLE",
+        ("I,Version", "I,Size"),
+    )
+
+    __IMAGE_DYNAMIC_RELOCATION_format__ = (
+        "IMAGE_DYNAMIC_RELOCATION",
+        ("I,Symbol", "I,BaseRelocSize"),
+    )
+
+    __IMAGE_DYNAMIC_RELOCATION64_format__ = (
+        "IMAGE_DYNAMIC_RELOCATION64",
+        ("Q,Symbol", "I,BaseRelocSize"),
+    )
+
+    __IMAGE_DYNAMIC_RELOCATION_V2_format__ = (
+        "IMAGE_DYNAMIC_RELOCATION_V2",
+        ("I,HeaderSize", "I,FixupInfoSize", "I,Symbol", "I,SymbolGroup", 
"I,Flags"),
+    )
+
+    __IMAGE_DYNAMIC_RELOCATION64_V2_format__ = (
+        "IMAGE_DYNAMIC_RELOCATION64_V2",
+        ("I,HeaderSize", "I,FixupInfoSize", "Q,Symbol", "I,SymbolGroup", 
"I,Flags"),
+    )
+
     __IMAGE_BOUND_IMPORT_DESCRIPTOR_format__ = (
         "IMAGE_BOUND_IMPORT_DESCRIPTOR",
         ("I,TimeDateStamp", "H,OffsetModuleName", 
"H,NumberOfModuleForwarderRefs"),
@@ -2772,6 +2884,12 @@
         # The number of imports parsed in this file
         self.__total_import_symbols = 0
 
+        self.dynamic_relocation_format_by_symbol = {
+            3: PE.__IMAGE_IMPORT_CONTROL_TRANSFER_DYNAMIC_RELOCATION_format__,
+            4: PE.__IMAGE_INDIR_CONTROL_TRANSFER_DYNAMIC_RELOCATION_format__,
+            5: PE.__IMAGE_SWITCHTABLE_BRANCH_DYNAMIC_RELOCATION_format__,
+        }
+
         fast_load = fast_load if fast_load is not None else 
globals()["fast_load"]
         try:
             self.__parse__(name, data, fast_load)
@@ -2819,6 +2937,28 @@
 
         return structure
 
+    def __unpack_data_with_bitfields__(self, format, data, file_offset):
+        """Apply structure format to raw data.
+
+        Returns an unpacked structure object if successful, None otherwise.
+        """
+
+        structure = StructureWithBitfields(format, file_offset=file_offset)
+
+        try:
+            structure.__unpack__(data)
+        except PEFormatError as err:
+            self.__warnings.append(
+                'Corrupt header "{0}" at file offset {1}. Exception: 
{2}'.format(
+                    format[0], file_offset, err
+                )
+            )
+            return None
+
+        self.__structures__.append(structure)
+
+        return structure
+
     def __parse__(self, fname, data, fast_load):
         """Parse a Portable Executable file.
 
@@ -2865,8 +3005,8 @@
                 # zero) or 15% (if non-zero) of the file's contents. There are
                 # legitimate PEs where 0x00 bytes are close to 50% of the whole
                 # file's contents.
-                if (byte == 0 and 1.0 * byte_count / len(self.__data__) > 0.5) 
or (
-                    byte != 0 and 1.0 * byte_count / len(self.__data__) > 0.15
+                if (byte == 0 and byte_count / len(self.__data__) > 0.5) or (
+                    byte != 0 and byte_count / len(self.__data__) > 0.15
                 ):
                     self.__warnings.append(
                         (
@@ -3848,8 +3988,10 @@
         """"""
 
         if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE:
+            load_config_dir_sz = self.get_dword_at_rva(rva)
             format = self.__IMAGE_LOAD_CONFIG_DIRECTORY_format__
         elif self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
+            load_config_dir_sz = self.get_dword_at_rva(rva)
             format = self.__IMAGE_LOAD_CONFIG_DIRECTORY64_format__
         else:
             self.__warnings.append(
@@ -3858,6 +4000,17 @@
             )
             return None
 
+        # load config directory size can be less than represented by 'format' 
variable,
+        # generate truncated format which correspond load config directory size
+        fields_counter = 0
+        cumulative_sz = 0
+        for field in format[1]:
+            fields_counter += 1
+            cumulative_sz += STRUCT_SIZEOF_TYPES[field.split(",")[0]]
+            if cumulative_sz == load_config_dir_sz:
+                break
+        format = (format[0], format[1][:fields_counter])
+
         load_config_struct = None
         try:
             load_config_struct = self.__unpack_data__(
@@ -3873,11 +4026,113 @@
         if not load_config_struct:
             return None
 
-        return LoadConfigData(struct=load_config_struct)
+        dynamic_relocations = None
+        if fields_counter > 35:
+            dynamic_relocations = self.parse_dynamic_relocations(
+                load_config_struct.DynamicValueRelocTableOffset,
+                load_config_struct.DynamicValueRelocTableSection,
+            )
+
+        return LoadConfigData(
+            struct=load_config_struct, dynamic_relocations=dynamic_relocations
+        )
+
+    def parse_dynamic_relocations(
+        self, dynamic_value_reloc_table_offset, 
dynamic_value_reloc_table_section
+    ):
+        if not dynamic_value_reloc_table_offset:
+            return None
+        if not dynamic_value_reloc_table_section:
+            return None
+
+        if dynamic_value_reloc_table_section > len(self.sections):
+            return None
+
+        section = self.sections[dynamic_value_reloc_table_section - 1]
+        rva = section.VirtualAddress + dynamic_value_reloc_table_offset
+        image_dynamic_reloc_table_struct = None
+        reloc_table_size = Structure(
+            self.__IMAGE_DYNAMIC_RELOCATION_TABLE_format__
+        ).sizeof()
+        try:
+            image_dynamic_reloc_table_struct = self.__unpack_data__(
+                self.__IMAGE_DYNAMIC_RELOCATION_TABLE_format__,
+                self.get_data(rva, reloc_table_size),
+                file_offset=self.get_offset_from_rva(rva),
+            )
+        except PEFormatError:
+            self.__warnings.append(
+                "Invalid IMAGE_DYNAMIC_RELOCATION_TABLE information. Can't 
read "
+                "data at RVA: 0x%x" % rva
+            )
+
+        if image_dynamic_reloc_table_struct.Version != 1:
+            self.__warnings.append(
+                "No pasring available for 
IMAGE_DYNAMIC_RELOCATION_TABLE.Version = %d",
+                image_dynamic_reloc_table_struct.Version,
+            )
+            return None
+
+        rva += reloc_table_size
+        end = rva + image_dynamic_reloc_table_struct.Size
+        dynamic_relocations = []
+
+        while rva < end:
+            format = self.__IMAGE_DYNAMIC_RELOCATION_format__
+
+            if self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS:
+                format = self.__IMAGE_DYNAMIC_RELOCATION64_format__
+
+            rlc_size = Structure(format).sizeof()
+
+            try:
+                dynamic_rlc = self.__unpack_data__(
+                    format,
+                    self.get_data(rva, rlc_size),
+                    file_offset=self.get_offset_from_rva(rva),
+                )
+            except PEFormatError:
+                self.__warnings.append(
+                    "Invalid relocation information. Can't read "
+                    "data at RVA: 0x%x" % rva
+                )
+                dynamic_rlc = None
+
+            if not dynamic_rlc:
+                break
+
+            rva += rlc_size
+            symbol = dynamic_rlc.Symbol
+            size = dynamic_rlc.BaseRelocSize
+
+            if 3 <= symbol <= 5:
+                relocations = self.parse_image_base_relocation_list(
+                    rva, size, self.dynamic_relocation_format_by_symbol[symbol]
+                )
+                dynamic_relocations.append(
+                    DynamicRelocationData(
+                        struct=dynamic_rlc, symbol=symbol, 
relocations=relocations
+                    )
+                )
+
+            if symbol > 5:
+                relocations = self.parse_image_base_relocation_list(rva, size)
+                dynamic_relocations.append(
+                    DynamicRelocationData(
+                        struct=dynamic_rlc, symbol=symbol, 
relocations=relocations
+                    )
+                )
+
+            rva += size
+
+        return dynamic_relocations
 
     def parse_relocations_directory(self, rva, size):
         """"""
 
+        return self.parse_image_base_relocation_list(rva, size)
+
+    def parse_image_base_relocation_list(self, rva, size, fmt=None):
         rlc_size = Structure(self.__IMAGE_BASE_RELOCATION_format__).sizeof()
         end = rva + size
 
@@ -3921,9 +4176,14 @@
                 )
                 break
 
-            reloc_entries = self.parse_relocations(
-                rva + rlc_size, rlc.VirtualAddress, rlc.SizeOfBlock - rlc_size
-            )
+            if fmt is None:
+                reloc_entries = self.parse_relocations(
+                    rva + rlc_size, rlc.VirtualAddress, rlc.SizeOfBlock - 
rlc_size
+                )
+            else:
+                reloc_entries = self.parse_relocations_with_format(
+                    rva + rlc_size, rlc.VirtualAddress, rlc.SizeOfBlock - 
rlc_size, fmt
+                )
 
             relocations.append(BaseRelocationData(struct=rlc, 
entries=reloc_entries))
 
@@ -3944,7 +4204,7 @@
             return []
 
         entries = []
-        offsets_and_type = []
+        offsets_and_type = set()
         for idx in range(int(len(data) / 2)):
 
             entry = self.__unpack_data__(
@@ -3965,9 +4225,8 @@
                     "at RVA: 0x%x" % (reloc_offset + rva)
                 )
                 break
-            if len(offsets_and_type) >= 1000:
-                offsets_and_type.pop()
-            offsets_and_type.insert(0, (reloc_offset, reloc_type))
+
+            offsets_and_type.add((reloc_offset, reloc_type))
 
             entries.append(
                 RelocationData(
@@ -3978,6 +4237,46 @@
 
         return entries
 
+    def parse_relocations_with_format(self, data_rva, rva, size, format):
+        """"""
+
+        try:
+            data = self.get_data(data_rva, size)
+            file_offset = self.get_offset_from_rva(data_rva)
+        except PEFormatError:
+            self.__warnings.append(f"Bad RVA in relocation data: 
0x{data_rva:x}")
+            return []
+
+        entry_size = StructureWithBitfields(format).sizeof()
+        entries = []
+        offsets = set()
+        for idx in range(int(len(data) / entry_size)):
+
+            entry = self.__unpack_data_with_bitfields__(
+                format,
+                data[idx * entry_size : (idx + 1) * entry_size],
+                file_offset=file_offset,
+            )
+
+            if not entry:
+                break
+
+            reloc_offset = entry.PageRelativeOffset
+            if reloc_offset in offsets:
+                self.__warnings.append(
+                    "Overlapping offsets in relocation data "
+                    "at RVA: 0x%x" % (reloc_offset + rva)
+                )
+                break
+            offsets.add(reloc_offset)
+
+            entries.append(
+                RelocationData(struct=entry, base_rva=rva, rva=reloc_offset + 
rva)
+            )
+            file_offset += entry_size
+
+        return entries
+
     def parse_debug_directory(self, rva, size):
         """"""
 
@@ -4024,13 +4323,13 @@
                     __CV_INFO_PDB70_format__ = [
                         "CV_INFO_PDB70",
                         [
-                            "I,CvSignature",
+                            "4s,CvSignature",
                             "I,Signature_Data1",  # Signature is of GUID type
                             "H,Signature_Data2",
                             "H,Signature_Data3",
-                            "8s,Signature_Data4",
-                            # 'H,Signature_Data5',
-                            # 'I,Signature_Data6',
+                            "B,Signature_Data4",
+                            "B,Signature_Data5",
+                            "6s,Signature_Data6",
                             "I,Age",
                         ],
                     ]
@@ -4051,6 +4350,27 @@
                     dbg_type = self.__unpack_data__(
                         __CV_INFO_PDB70_format__, dbg_type_data, 
dbg_type_offset
                     )
+                    if dbg_type is not None:
+                        dbg_type.Signature_Data6_value = struct.unpack(
+                            ">Q", b"\0\0" + dbg_type.Signature_Data6
+                        )[0]
+                        dbg_type.Signature_String = (
+                            str(
+                                uuid.UUID(
+                                    fields=(
+                                        dbg_type.Signature_Data1,
+                                        dbg_type.Signature_Data2,
+                                        dbg_type.Signature_Data3,
+                                        dbg_type.Signature_Data4,
+                                        dbg_type.Signature_Data5,
+                                        dbg_type.Signature_Data6_value,
+                                    )
+                                )
+                            )
+                            .replace("-", "")
+                            .upper()
+                            + f"{dbg_type.Age:X}"
+                        )
 
                 elif dbg_type_data[:4] == b"NB10":
                     # pdb2.0
@@ -5049,7 +5369,7 @@
             symbol_name = self.get_string_at_rva(
                 symbol_name_address, MAX_SYMBOL_NAME_LENGTH
             )
-            if not is_valid_function_name(symbol_name):
+            if not is_valid_function_name(symbol_name, 
relax_allowed_characters=True):
                 export_parsing_loop_completed_normally = False
                 break
             try:
@@ -5336,6 +5656,16 @@
         raise Exception("Invalid hashing algorithm specified")
 
     def get_imphash(self):
+        """Return the imphash of the PE file.
+
+        Creates a hash based on imported symbol names and their specific order 
within
+        the executable:
+        https://www.mandiant.com/resources/blog/tracking-malware-import-hashing
+
+        Returns:
+            the hexdigest of the MD5 hash of the exported symbols.
+        """
+
         impstrs = []
         exts = ["ocx", "sys", "dll"]
         if not hasattr(self, "DIRECTORY_ENTRY_IMPORT"):
@@ -5373,6 +5703,31 @@
 
         return md5(",".join(impstrs).encode()).hexdigest()
 
+    def get_exphash(self):
+        """Return the exphash of the PE file.
+
+        Similar to imphash, but based on exported symbol names and their 
specific order.
+
+        Returns:
+            the hexdigest of the SHA256 hash of the exported symbols.
+        """
+
+        if not hasattr(self, "DIRECTORY_ENTRY_EXPORT"):
+            return ""
+
+        if not hasattr(self.DIRECTORY_ENTRY_EXPORT, "symbols"):
+            return ""
+
+        export_list = [
+            e.name.decode().lower()
+            for e in self.DIRECTORY_ENTRY_EXPORT.symbols
+            if e and e.name is not None
+        ]
+        if len(export_list) == 0:
+            return ""
+
+        return sha256(",".join(export_list).encode()).hexdigest()
+
     def parse_import_directory(self, rva, size, dllnames_only=False):
         """Walk and parse the import directory."""
 
@@ -6060,6 +6415,13 @@
         """Checks if the PE file has relocation directory"""
         return hasattr(self, "DIRECTORY_ENTRY_BASERELOC")
 
+    def has_dynamic_relocs(self):
+        if hasattr(self, "DIRECTORY_ENTRY_LOAD_CONFIG"):
+            if self.DIRECTORY_ENTRY_LOAD_CONFIG.dynamic_relocations:
+                return True
+
+        return False
+
     def print_info(self, encoding="utf-8"):
         """Print all the PE header information in a human readable from."""
         print(self.dump_info(encoding=encoding))
@@ -7132,30 +7494,84 @@
                     relocation_difference
                 )
             if hasattr(self, "DIRECTORY_ENTRY_LOAD_CONFIG"):
-                if self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.LockPrefixTable:
-                    self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.LockPrefixTable += 
(
-                        relocation_difference
-                    )
-                if self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.EditList:
-                    self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.EditList += (
-                        relocation_difference
-                    )
-                if self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SecurityCookie:
-                    self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SecurityCookie += (
-                        relocation_difference
-                    )
-                if self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerTable:
-                    self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.SEHandlerTable += (
-                        relocation_difference
-                    )
-                if 
self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.GuardCFCheckFunctionPointer:
-                    
self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.GuardCFCheckFunctionPointer += (
+                load_config = self.DIRECTORY_ENTRY_LOAD_CONFIG.struct
+                if (
+                    hasattr(load_config, "LockPrefixTable")
+                    and load_config.LockPrefixTable
+                ):
+                    load_config.LockPrefixTable += relocation_difference
+                if hasattr(load_config, "EditList") and load_config.EditList:
+                    load_config.EditList += relocation_difference
+                if (
+                    hasattr(load_config, "SecurityCookie")
+                    and load_config.SecurityCookie
+                ):
+                    load_config.SecurityCookie += relocation_difference
+                if (
+                    hasattr(load_config, "SEHandlerTable")
+                    and load_config.SEHandlerTable
+                ):
+                    load_config.SEHandlerTable += relocation_difference
+                if (
+                    hasattr(load_config, "GuardCFCheckFunctionPointer")
+                    and load_config.GuardCFCheckFunctionPointer
+                ):
+                    load_config.GuardCFCheckFunctionPointer += 
relocation_difference
+                if (
+                    hasattr(load_config, "GuardCFDispatchFunctionPointer")
+                    and load_config.GuardCFDispatchFunctionPointer
+                ):
+                    load_config.GuardCFDispatchFunctionPointer += 
relocation_difference
+                if (
+                    hasattr(load_config, "GuardCFFunctionTable")
+                    and load_config.GuardCFFunctionTable
+                ):
+                    load_config.GuardCFFunctionTable += relocation_difference
+                if (
+                    hasattr(load_config, "GuardAddressTakenIatEntryTable")
+                    and load_config.GuardAddressTakenIatEntryTable
+                ):
+                    load_config.GuardAddressTakenIatEntryTable += 
relocation_difference
+                if (
+                    hasattr(load_config, "GuardLongJumpTargetTable")
+                    and load_config.GuardLongJumpTargetTable
+                ):
+                    load_config.GuardLongJumpTargetTable += 
relocation_difference
+                if (
+                    hasattr(load_config, "DynamicValueRelocTable")
+                    and load_config.DynamicValueRelocTable
+                ):
+                    load_config.DynamicValueRelocTable += relocation_difference
+                if (
+                    self.PE_TYPE == OPTIONAL_HEADER_MAGIC_PE_PLUS
+                    and hasattr(load_config, "CHPEMetadataPointer")
+                    and load_config.CHPEMetadataPointer
+                ):
+                    load_config.CHPEMetadataPointer += relocation_difference
+                if (
+                    hasattr(load_config, "GuardRFFailureRoutine")
+                    and load_config.GuardRFFailureRoutine
+                ):
+                    load_config.GuardRFFailureRoutine += relocation_difference
+                if (
+                    hasattr(load_config, 
"GuardRFFailureRoutineFunctionPointer")
+                    and load_config.GuardRFFailureRoutineFunctionPointer
+                ):
+                    load_config.GuardRFVerifyStackPointerFunctionPointer += (
                         relocation_difference
                     )
-                if 
self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.GuardCFFunctionTable:
-                    
self.DIRECTORY_ENTRY_LOAD_CONFIG.struct.GuardCFFunctionTable += (
+                if (
+                    hasattr(load_config, 
"GuardRFVerifyStackPointerFunctionPointer")
+                    and load_config.GuardRFVerifyStackPointerFunctionPointer
+                ):
+                    load_config.GuardRFVerifyStackPointerFunctionPointer += (
                         relocation_difference
                     )
+                if (
+                    hasattr(load_config, "EnclaveConfigurationPointer")
+                    and load_config.EnclaveConfigurationPointer
+                ):
+                    load_config.EnclaveConfigurationPointer += 
relocation_difference
 
     def verify_checksum(self):
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pefile-2022.5.30/peutils.py 
new/pefile-2023.2.7/peutils.py
--- old/pefile-2022.5.30/peutils.py     2022-05-30 15:25:51.000000000 +0200
+++ new/pefile-2023.2.7/peutils.py      2023-01-07 20:42:11.000000000 +0100
@@ -1,18 +1,11 @@
-# -*- coding: Latin-1 -*-
+
 """peutils, Portable Executable utilities module
 
 
-Copyright (c) 2005-2022 Ero Carrera <ero.carr...@gmail.com>
+Copyright (c) 2005-2023 Ero Carrera <ero.carr...@gmail.com>
 
 All rights reserved.
 """
-from __future__ import division
-from future import standard_library
-
-standard_library.install_aliases()
-from builtins import range
-from builtins import object
-
 import os
 import re
 import string
@@ -586,7 +579,7 @@
         if s_entropy > 7.4:
             total_compressed_data += s_length
 
-    if ((1.0 * total_compressed_data) / total_pe_data_length) > 0.2:
+    if (total_compressed_data / total_pe_data_length) > 0.2:
         has_significant_amount_of_compressed_data = True
 
     return has_significant_amount_of_compressed_data
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pefile-2022.5.30/setup.py 
new/pefile-2023.2.7/setup.py
--- old/pefile-2022.5.30/setup.py       2022-05-30 15:24:42.000000000 +0200
+++ new/pefile-2023.2.7/setup.py        2023-02-06 23:44:23.000000000 +0100
@@ -5,8 +5,6 @@
 import re
 import sys
 
-if sys.version_info.major == 3:
-    from io import open
 
 try:
     from setuptools import setup, Command
@@ -16,8 +14,8 @@
 from unittest import TestLoader, TextTestRunner
 
 
-os.environ['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true'
-os.environ['COPYFILE_DISABLE'] = 'true'
+os.environ["COPY_EXTENDED_ATTRIBUTES_DISABLE"] = "true"
+os.environ["COPYFILE_DISABLE"] = "true"
 
 
 def _read_doc():
@@ -25,12 +23,8 @@
     Parse docstring from file 'pefile.py' and avoid importing
     this module directly.
     """
-    if sys.version_info.major == 2:
-        with open('pefile.py', 'r') as f:
-            tree = ast.parse(f.read())
-    else:
-        with open('pefile.py', 'r', encoding='utf-8') as f:
-            tree = ast.parse(f.read())
+    with open("pefile.py", "r", encoding="utf-8") as f:
+        tree = ast.parse(f.read())
     return ast.get_docstring(tree)
 
 
@@ -42,18 +36,15 @@
     __version__, __author__, __contact__,
     """
     regex = attr_name + r"\s+=\s+['\"](.+)['\"]"
-    if sys.version_info.major == 2:
-        with open('pefile.py', 'r') as f:
-            match = re.search(regex, f.read())
-    else:
-        with open('pefile.py', 'r', encoding='utf-8') as f:
-            match = re.search(regex, f.read())
+    with open("pefile.py", "r", encoding="utf-8") as f:
+        match = re.search(regex, f.read())
     # Second item in the group is the value of attribute.
     return match.group(1)
 
 
 class TestCommand(Command):
     """Run tests."""
+
     user_options = []
 
     def initialize_options(self):
@@ -63,33 +54,33 @@
         pass
 
     def run(self):
-        test_suite = TestLoader().discover('./tests', pattern='*_test.py')
+        test_suite = TestLoader().discover("./tests", pattern="*_test.py")
         test_results = TextTestRunner(verbosity=2).run(test_suite)
 
 
-setup(name = 'pefile',
-    version = _read_attr('__version__'),
-    description = 'Python PE parsing module',
-    author = _read_attr('__author__'),
-    author_email = _read_attr('__contact__'),
-    url = 'https://github.com/erocarrera/pefile',
-    
download_url='https://github.com/erocarrera/pefile/releases/download/v2022.5.30/pefile-2022.5.30.tar.gz',
-    keywords = ['pe', 'exe', 'dll', 'pefile', 'pecoff'],
-    classifiers = [
-        'Development Status :: 5 - Production/Stable',
-        'Intended Audience :: Developers',
-        'Intended Audience :: Science/Research',
-        'Natural Language :: English',
-        'Operating System :: OS Independent',
-        'Programming Language :: Python',
-        'Topic :: Software Development :: Libraries :: Python Modules'],
-    long_description = "\n".join(_read_doc().split('\n')),
+setup(
+    name="pefile",
+    version=_read_attr("__version__"),
+    description="Python PE parsing module",
+    author=_read_attr("__author__"),
+    author_email=_read_attr("__contact__"),
+    url="https://github.com/erocarrera/pefile";,
+    
download_url="https://github.com/erocarrera/pefile/releases/download/v2023.2.7/pefile-2023.2.7.tar.gz";,
+    keywords=["pe", "exe", "dll", "pefile", "pecoff"],
+    classifiers=[
+        "Development Status :: 5 - Production/Stable",
+        "Intended Audience :: Developers",
+        "Intended Audience :: Science/Research",
+        "Natural Language :: English",
+        "Operating System :: OS Independent",
+        "Programming Language :: Python",
+        "Topic :: Software Development :: Libraries :: Python Modules",
+    ],
+    long_description="\n".join(_read_doc().split("\n")),
     cmdclass={"test": TestCommand},
-    py_modules = ['pefile', 'peutils'],
+    py_modules=["pefile", "peutils"],
     python_requires=">=3.6.0",
-    packages = ['ordlookup'],
-    install_requires=[
-          'future',
-    ],
+    packages=["ordlookup"],
+    install_requires=[],
     license="MIT",
 )

Reply via email to