#219 Revert the automatic reformatting with black
Opened 2 months ago by zbyszek. Modified 2 months ago
fedora-rust/ zbyszek/rust2rpm unblackify  into  main

file modified
+1 -1
@@ -1,3 +1,3 @@ 

  from . import licensing

  

- __version__ = "22"

+ __version__ = '22'

file modified
+133 -236
@@ -25,60 +25,49 @@ 

  CACHEDIR = os.path.join(XDG_CACHE_HOME, "rust2rpm")

  API_URL = "https://crates.io/api/v1/"

  DIST_GIT_URL = "https://src.fedoraproject.org/api/0/"

- LICENSES = re.compile(

-     r"""

-     COPYING(?:[.-].*)?|COPYRIGHT(?:[.-].*)?|

-     EULA(?:[.-].*)?|[Ll]icen[cs]e|[Ll]icen[cs]e.*|

-     (?:.*[.-])?(?:UN)?LICEN[CS]E(?:[.-].*)?|NOTICE(?:[.-].*)?|

-     PATENTS(?:[.-].*)?|

-     (?:agpl|l?gpl)[.-].*|CC-BY-.*|

-     (?:AGPL|APACHE|BSD|GFDL|GNU|L?GPL|MIT|MPL|OFL)-.*[0-9].*

-     """,

-     re.VERBOSE,

- )

+ LICENSES = re.compile(r"""

+          COPYING(?:[.-].*)?|COPYRIGHT(?:[.-].*)?|

+          EULA(?:[.-].*)?|[Ll]icen[cs]e|[Ll]icen[cs]e.*|

+          (?:.*[.-])?(?:UN)?LICEN[CS]E(?:[.-].*)?|NOTICE(?:[.-].*)?|

+          PATENTS(?:[.-].*)?|

+          (?:agpl|l?gpl)[.-].*|CC-BY-.*|

+          (?:AGPL|APACHE|BSD|GFDL|GNU|L?GPL|MIT|MPL|OFL)-.*[0-9].*

+          """, re.VERBOSE)

  

  # [target.'cfg(not(any(target_os="windows", target_os="macos")))'.dependencies]

  # [target."cfg(windows)".dependencies.winapi]

  # [target."cfg(target_arch = \"wasm32\")".dev-dependencies.wasm-bindgen-test]

  

- TARGET_DEPENDENCY_LINE = re.compile(

-     r"""

-     ^ \[ target\.(?P<cfg>(?P<quote>['"])cfg\(.*\)(?P=quote))

-     \.

-     (?P<type> dependencies|build-dependencies|dev-dependencies)

-     (?:\. (?P<feature>[a-zA-Z0-9_-]+) )?

-     \] \s* $

-     """,

-     re.VERBOSE,

- )

- 

+ TARGET_DEPENDENCY_LINE = re.compile(r'''

+          ^ \[ target\.(?P<cfg>(?P<quote>['"])cfg\(.*\)(?P=quote))

+              \.

+              (?P<type> dependencies|build-dependencies|dev-dependencies)

+              (?:\. (?P<feature>[a-zA-Z0-9_-]+) )?

+          \] \s* $

+          ''', re.VERBOSE)

  

  def sortify(func):

      """Return a sorted list from a generator"""

- 

      def wrapper(*args, **kwargs):

          return sorted(func(*args, **kwargs))

- 

      return functools.update_wrapper(wrapper, func)

  

- 

  def read_os_release():

      try:

-         f = open("/etc/os-release")

+         f = open('/etc/os-release')

      except FileNotFoundError:

-         f = open("/usr/lib/os-release")

+         f = open('/usr/lib/os-release')

  

      for line in f:

          line = line.rstrip()

-         if not line or line.startswith("#"):

+         if not line or line.startswith('#'):

              continue

-         if m := re.match(r"([A-Z][A-Z_0-9]+)=(.*)", line):

+         if m := re.match(r'([A-Z][A-Z_0-9]+)=(.*)', line):

              name, val = m.groups()

-             if val and val[0] in "\"'":

+             if val and val[0] in '"\'':

                  val = ast.literal_eval(val)

              yield name, val

  

- 

  def get_default_target():

      os_release = dict(read_os_release())

      os_id = os_release.get("ID")
@@ -95,15 +84,12 @@ 

      else:

          return "plain"

  

- 

  def file_mtime(path):

      return datetime.fromtimestamp(os.stat(path).st_mtime, timezone.utc).isoformat()

  

- 

  def package_name_suffixed(name, suffix):

-     joiner = "_" if suffix and name[-1].isdigit() else ""

-     return "rust-" + name + joiner + (suffix or "")

- 

+     joiner = '_' if suffix and name[-1].isdigit() else ''

+     return 'rust-' + name + joiner + (suffix or '')

  

  def local_toml(toml, version):

      if os.path.isdir(toml):
@@ -116,12 +102,10 @@ 

  

      return toml, None, version, doc_files, license_files

  

- 

  def local_crate(crate, version):

      cratename, version = os.path.basename(crate)[:-6].rsplit("-", 1)

      return crate, cratename, version

  

- 

  def query_newest_version(crate):

      url = requests.compat.urljoin(API_URL, f"crates/{crate}/versions")

      req = requests.get(url, headers={"User-Agent": "rust2rpm"})
@@ -130,16 +114,15 @@ 

      for struct in versions:

          version = struct["num"]

          if struct["yanked"]:

-             log.info(f"Ignoring yanked version {version!r}.")

-         elif re.search("alpha|beta|rc|pre", version):

-             log.info(f"Ignoring pre-release version {version!r}.")

+             log.info(f'Ignoring yanked version {version!r}.')

+         elif re.search('alpha|beta|rc|pre', version):

+             log.info(f'Ignoring pre-release version {version!r}.')

          else:

-             log.success(f"Using latest stable version {version!r}.")

+             log.success(f'Using latest stable version {version!r}.')

              return version

  

      raise ValueError("Couldn't find any release versions. Specify a version explicitly.")

  

- 

  def download(crate, version):

      if version is None:

          # Now we need to get latest version
@@ -154,17 +137,11 @@ 

          req.raise_for_status()

          total = int(req.headers["Content-Length"])

          with util.remove_on_error(cratef), open(cratef, "wb") as f:

-             for chunk in tqdm.tqdm(

-                 req.iter_content(),

-                 f"Downloading {cratef_base}",

-                 total=total,

-                 unit="B",

-                 unit_scale=True,

-             ):

+             for chunk in tqdm.tqdm(req.iter_content(), f"Downloading {cratef_base}",

+                                    total=total, unit="B", unit_scale=True):

                  f.write(chunk)

      return cratef, crate, version

  

- 

  @contextlib.contextmanager

  def files_from_crate(cratef, crate, version):

      """Unpacks cratef and returns path to toml file, list of doc files, list of license files"""
@@ -183,24 +160,18 @@ 

          license_files = get_license_files(root_path)

          yield toml, doc_files, license_files

  

- 

  def filter_out_features_re(dropped_features):

      # This is a bit simplistic. But it doesn't seem worth the trouble to write

      # a grammar for this. Can be always done later. If we parse this using a

      # grammar, we beget the question how to preserve formatting idiosyncrasies.

      # Regexp replacement makes it trivial to minimize changes.

-     match_features = "|".join(dropped_features)

-     match_suffix = f"(?:/[{cfg.IDENT_CHARS[1]}]+)?"

- 

-     return re.compile(

-         rf"""

-         (?P<comma> ,)? \s* (?P<quote>['"])

-         ({match_features}) {match_suffix}

-         (?P=quote) \s* (?(comma) |,?) \s*

-         """,

-         re.VERBOSE,

-     )

+     match_features = '|'.join(dropped_features)

+     match_suffix = f'(?:/[{cfg.IDENT_CHARS[1]}]+)?'

  

+     return re.compile(fr'''(?P<comma> ,)? \s* (?P<quote>['"])

+                            ({match_features}) {match_suffix}

+                            (?P=quote) \s* (?(comma) |,?) \s*

+                       ''', re.VERBOSE)

  

  def drop_foreign_dependencies(lines):

      dropped_lines = 0
@@ -210,20 +181,20 @@ 

      value = True

      for line in lines:

          if m := TARGET_DEPENDENCY_LINE.match(line):

-             expr = m.group("cfg")

+             expr = m.group('cfg')

              expr = ast.literal_eval(expr)

              try:

                  value = cfg.parse_and_evaluate(expr)

              except (ValueError, cfg.ParseException):

-                 log.warn(f"Could not evaluate {expr!r}, treating as true.")

+                 log.warn(f'Could not evaluate {expr!r}, treating as true.')

                  value = True

  

              if not value:

-                 feature = m.group("feature")

-                 log.info(f"Dropping target-specific dependency on {feature!r}.")

+                 feature = m.group('feature')

+                 log.info(f'Dropping target-specific dependency on {feature!r}.')

                  dropped_features.add(feature)

  

-         elif line.startswith("["):

+         elif line.startswith('['):

              # previous section ended, let's keep printing lines again

              value = True

  
@@ -240,12 +211,12 @@ 

      in_features = False

      filt = filter_out_features_re(dropped_features)

      for line in good_lines:

-         if line.rstrip() == "[features]":

+         if line.rstrip() == '[features]':

              in_features = True

-         elif line.startswith("["):

+         elif line.startswith('['):

              in_features = False

          elif in_features:

-             line = re.sub(filt, "", line)

+             line = re.sub(filt, '', line)

              if not line:

                  continue

  
@@ -255,9 +226,9 @@ 

  

  

  def make_diff(path, lines1, mtime1, lines2, mtime2):

-     return list(

-         difflib.unified_diff(lines1, lines2, fromfile=path, tofile=path, fromfiledate=mtime1, tofiledate=mtime2)

-     )

+     return list(difflib.unified_diff(lines1, lines2,

+                                      fromfile=path, tofile=path,

+                                      fromfiledate=mtime1, tofiledate=mtime2))

  

  

  def make_patches(args, version, toml):
@@ -304,15 +275,15 @@ 

          mtime_after2 = file_mtime(toml)

          toml_after2 = open(toml).readlines()

  

-         diff2 = make_diff(toml_path, toml_after, mtime_before, toml_after2, mtime_after2)

+         diff2 = make_diff(toml_path,

+                           toml_after, mtime_before,

+                           toml_after2, mtime_after2)

  

      return diff1, diff2

  

- 

  def _is_path(path):

      return "/" in path or path in {".", ".."}

  

- 

  @sortify

  def get_license_files(path):

      """Heuristic match on file names to detect license files"""
@@ -335,18 +306,15 @@ 

              if LICENSES.match(f):

                  yield os.path.relpath(os.path.join(root, f), path)

  

- 

  @sortify

  def get_doc_files(path):

      """Heuristic match on file names to detect documentation files"""

-     plus = re.compile(

-         r"""

+     plus = re.compile(r"""

          .*\.(?:md|markdown|mdown|mkdn|rst|txt)|AUTHORS|

          AUTHORS[.-].*|CONTRIBUTORS|CONTRIBUTORS[.-].*|README|

          README[.-].*|CHANGELOG|CHANGELOG[.-].*|TODO|TODO[.-].*

          """,

-         re.IGNORECASE | re.VERBOSE,

-     )

+         re.IGNORECASE | re.VERBOSE)

      minus = re.compile(r"CMakeLists\.txt|.*\.tpl|.*\.in")

  

      for root, dirs, files in os.walk(path, topdown=True):
@@ -355,7 +323,6 @@ 

              if plus.fullmatch(f) and not LICENSES.fullmatch(f) and not minus.fullmatch(f):

                  yield os.path.relpath(os.path.join(root, f), path)

  

- 

  def get_package_info(package):

      """Download information about package from dist-git.

  
@@ -372,12 +339,12 @@ 

      url = requests.compat.urljoin(DIST_GIT_URL, f"rpms/{package}")

      req = requests.get(url, headers={"User-Agent": "rust2rpm"})

      json = req.json()

-     if "name" not in json:

+     if 'name' not in json:

          return None

  

      # E.g. https://src.fedoraproject.org/rpms/rust-tiny_http0.6/blob/rawhide/f/rust-tiny_http0.6.spec

-     full_url = json["full_url"]

-     spec_url = requests.compat.urljoin(full_url, f"blob/rawhide/f/rust-{package}.spec")

+     full_url = json['full_url']

+     spec_url = requests.compat.urljoin(full_url, f'blob/rawhide/f/rust-{package}.spec')

      req = requests.head(spec_url, headers={"User-Agent": "rust2rpm"})

  

      if not req.ok:
@@ -387,7 +354,6 @@ 

  

      return json

  

- 

  def make_diff_metadata(args, crate, version):

      if _is_path(crate):

          # Only things that look like a paths are considered local arguments
@@ -454,13 +420,11 @@ 

      but a compat package would almost always be created from an existing

      dist-git directory, hence there'd be a spec file, so we can ignore this.

      """

-     specs = glob.glob("*.spec")

+     specs = glob.glob('*.spec')

  

      if len(specs) > 1:

-         log.error(

-             f"Found multiple spec files in the current working directory; "

-             + "unable to determine crate name automatically."

-         )

+         log.error('Found multiple spec files in the current working directory;'

+                   ' unable to determine crate name automatically.')

          return None

  

      if len(specs) == 1:
@@ -468,138 +432,79 @@ 

          spec = specs[0]

  

          for line in open(spec):

-             if m := re.match(r"^%(?:global|define)\s+crate\s+(\S+)\s+", line):

+             if m := re.match(r'^%(?:global|define)\s+crate\s+(\S+)\s+', line):

                  if crate:

-                     log.error(

-                         f"Found multiple definitions of the '%crate' macro in {spec!r}; "

-                         + f"unable to determine crate name automatically."

-                     )

+                     log.error(f"Found multiple definitions of the '%crate' macro in {spec!r};"

+                               " unable to determine crate name automatically.")

                      return None

                  crate = m.group(1)

-                 if "%" in crate:

-                     log.error(f"The value of the %crate macro appears to contain other macros and cannot be parsed.")

+                 if '%' in crate:

+                     log.error('The value of the %crate macro appears to contain other macros and cannot be parsed.')

                      return None

          if crate:

-             log.success(f"Found valid spec file {spec!r} for the {crate!r} crate.")

+             log.success(f'Found valid spec file {spec!r} for the {crate!r} crate.')

          else:

-             log.error(f"Invalid spec file {spec!r}; unable to determine crate name automatically.")

+             log.error(f'Invalid spec file {spec!r}; unable to determine crate name automatically.')

          return crate

  

      dirname = os.path.basename(os.getcwd())

-     if m := re.match("^rust-([a-z+0-9_-]+)$", dirname):

+     if m := re.match('^rust-([a-z+0-9_-]+)$', dirname):

          crate = m.group(1)

-         log.info(f"Continuing with crate name {crate!r} based on the current working directory.")

+         log.info(f'Continuing with crate name {crate!r} based on the current working directory.')

          return crate

  

      return None

  

- 

  def get_parser():

      default_target = get_default_target()

  

-     parser = argparse.ArgumentParser("rust2rpm", formatter_class=argparse.RawTextHelpFormatter)

-     parser.add_argument(

-         "--show-license-map",

-         action="store_true",

-         help="Print license mappings and exit",

-     )

-     parser.add_argument(

-         "--translate-license",

-         action="store_true",

-         help="Print mapping for specified license and exit",

-     )

-     parser.add_argument(

-         "--no-auto-changelog-entry",

-         action="store_false",

-         default=True,

-         dest="auto_changelog_entry",

-         help="Do not generate a changelog entry",

-     )

-     parser.add_argument(

-         "--no-existence-check",

-         action="store_false",

-         default=True,

-         dest="existence_check",

-         help="Do not check whether the package already exists in dist-git",

-     )

-     parser.add_argument("-", "--stdout", action="store_true", help="Print spec and patches into stdout")

-     parser.add_argument(

-         "-t",

-         "--target",

-         action="store",

-         choices=("plain", "fedora", "mageia", "opensuse"),

-         default=default_target,

-         help="Distribution target",

-     )

-     parser.add_argument(

-         "--no-patch-foreign",

-         action="store_false",

-         default=True,

-         dest="patch_foreign",

-         help="Do not automatically drop foreign dependencies in Cargo.toml",

-     )

-     parser.add_argument(

-         "-p",

-         "--patch",

-         action="store_true",

-         help="Do manual patching of Cargo.toml",

-     )

-     parser.add_argument(

-         "-s",

-         "--store-crate",

-         action="store_true",

-         help="Store crate in current directory",

-     )

-     parser.add_argument(

-         "-a",

-         "--rpmautospec",

-         action="store_true",

-         default=None,

-         help="Use autorelease and autochangelog features",

-     )

-     parser.add_argument(

-         "--no-rpmautospec",

-         action="store_false",

-         dest="rpmautospec",

-         help="Do not use rpmautospec",

-     )

-     parser.add_argument(

-         "--relative-license-paths",

-         action="store_true",

-         help="Put all license files in main license directory",

-     )

-     parser.add_argument(

-         "--all-features",

-         action="store_true",

-         help="Activate all available features",

-     )

-     parser.add_argument(

-         "--dynamic-buildrequires",

-         action="store_true",

-         default=None,

-         help="Use dynamic BuildRequires feature",

-     )

-     parser.add_argument(

-         "--no-dynamic-buildrequires",

-         action="store_false",

-         dest="dynamic_buildrequires",

-         help="Do not use dynamic BuildRequires feature",

-     )

-     parser.add_argument(

-         "--suffix",

-         action="store",

-         help="Package suffix",

-     )

-     parser.add_argument(

-         "crate",

-         help="crates.io name\n" "path/to/local.crate\n" "path/to/project/",

-         nargs="?",

-     )

-     parser.add_argument(

-         "version",

-         nargs="?",

-         help="crates.io version",

-     )

+     parser = argparse.ArgumentParser("rust2rpm",

+                                      formatter_class=argparse.RawTextHelpFormatter)

+     parser.add_argument("--show-license-map", action="store_true",

+                         help="Print license mappings and exit")

+     parser.add_argument("--translate-license", action="store_true",

+                         help="Print mapping for specified license and exit")

+     parser.add_argument("--no-auto-changelog-entry", action="store_false",

+                         default=True, dest="auto_changelog_entry",

+                         help="Do not generate a changelog entry")

+     parser.add_argument("--no-existence-check", action="store_false",

+                         default=True, dest="existence_check",

+                         help="Do not check whether the package already exists in dist-git")

+     parser.add_argument("-", "--stdout", action="store_true",

+                         help="Print spec and patches into stdout")

+     parser.add_argument("-t", "--target", action="store",

+                         choices=("plain", "fedora", "mageia", "opensuse"), default=default_target,

+                         help="Distribution target")

+     parser.add_argument("--no-patch-foreign", action="store_false",

+                         default=True, dest="patch_foreign",

+                         help="Do not automatically drop foreign dependencies in Cargo.toml")

+     parser.add_argument("-p", "--patch", action="store_true",

+                         help="Do manual patching of Cargo.toml")

+     parser.add_argument("-s", "--store-crate", action="store_true",

+                         help="Store crate in current directory")

+     parser.add_argument("-a", "--rpmautospec", action="store_true",

+                         default=None,

+                         help="Use autorelease and autochangelog features")

+     parser.add_argument("--no-rpmautospec", action="store_false",

+                         dest="rpmautospec",

+                         help="Do not use rpmautospec")

+     parser.add_argument("--relative-license-paths", action="store_true",

+                         help="Put all license files in main license directory")

+     parser.add_argument("--all-features", action="store_true",

+                         help="Activate all available features")

+     parser.add_argument("--dynamic-buildrequires", action="store_true",

+                         default=None,

+                         help="Use dynamic BuildRequires feature")

+     parser.add_argument("--no-dynamic-buildrequires", action="store_false",

+                         dest="dynamic_buildrequires",

+                         help="Do not use dynamic BuildRequires feature")

+     parser.add_argument("--suffix", action="store",

+                         help="Package suffix")

+     parser.add_argument("crate", help="crates.io name\n"

+                                       "path/to/local.crate\n"

+                                       "path/to/project/",

+                         nargs="?")

+     parser.add_argument("version", nargs="?", help="crates.io version")

  

      return parser

  
@@ -630,10 +535,8 @@ 

  

      pkg_name = package_name_suffixed(metadata.name, args.suffix)

  

-     patch_files = (

-         f"{metadata.name}-fix-metadata-auto.diff" if diffs[0] else None,

-         f"{metadata.name}-fix-metadata.diff" if diffs[1] else None,

-     )

+     patch_files = (f"{metadata.name}-fix-metadata-auto.diff" if diffs[0] else None,

+                    f"{metadata.name}-fix-metadata.diff" if diffs[1] else None)

  

      spec_file = pathlib.Path(f"{pkg_name}.spec")

  
@@ -641,12 +544,11 @@ 

          # No specfile, so this is probably a new package

          if package_info := get_package_info(pkg_name):

              if args.suffix:

-                 log.warn(

-                     f"Version {args.suffix}.* of the crate {metadata.name!r} is already "

-                     + f"packaged for Fedora: {package_info['full_url']}"

-                 )

+                 log.warn(f"Version {args.suffix}.* of the crate {metadata.name!r} is already"

+                          f" packaged for Fedora: {package_info['full_url']}")

              else:

-                 log.warn(f"Crate {metadata.name!r} is already packaged for Fedora: {package_info['full_url']}")

+                 log.warn(f"Crate {metadata.name!r} is already packaged for Fedora:"

+                          f" {package_info['full_url']}")

  

              log.info("Re-run with --no-existence-check to create a new spec file from scratch.")

              sys.exit(1)
@@ -664,10 +566,8 @@ 

  

      # clean up configuration files with deprecated names

      if len(confs) > 1:

-         log.error(

-             "More than one *rust2rpm.conf file is present in this directory. "

-             + "Ensure that there is only one, and that it has the correct contents."

-         )

+         log.error("More than one *rust2rpm.conf file is present in this directory."

+                   " Ensure that there is only one, and that it has the correct contents.")

          sys.exit(1)

  

      if ".rust2rpm.conf" in confs and "rust2rpm.conf" not in confs:
@@ -683,23 +583,21 @@ 

  

      conf_all_features = conf[args.target].getboolean("all-features")

      if conf_all_features is False and args.all_features:

-         log.warn(

-             'Conflicting settings for enabling all features: The setting is "false"'

-             + 'in rust2rpm.conf but it was enabled with the "--all-features" CLI flag.'

-         )

+         log.warn("Conflicting settings for enabling all features: The setting is \"false\""

+                  " in rust2rpm.conf but it was enabled with the \"--all-features\" CLI flag.")

  

      spec_contents = generator.spec_file_render(

-         args=args,

-         pkg_name=pkg_name,

-         crate=crate,

-         metadata=metadata,

+         args = args,

+         pkg_name = pkg_name,

+         crate = crate,

+         metadata = metadata,

          patch_file_automatic=patch_files[0],

          patch_file_manual=patch_files[1],

-         packager=packager,

-         doc_files=doc_files,

-         license_files=license_files,

-         distconf=conf[args.target],

-         all_features=conf_all_features or args.all_features,

+         packager = packager,

+         doc_files = doc_files,

+         license_files = license_files,

+         distconf = conf[args.target],

+         all_features = conf_all_features or args.all_features,

      )

  

      if args.stdout:
@@ -712,13 +610,12 @@ 

      else:

          with open(spec_file, "w") as fobj:

              fobj.write(spec_contents)

-         log.success(f"Generated: {fobj.name}")

+         log.success(f'Generated: {fobj.name}')

          for fname, diff in zip(patch_files, diffs):

              if fname:

                  with open(fname, "w") as fobj:

                      fobj.writelines(diff)

-                 log.success(f"Generated: {fobj.name}")

- 

+                 log.success(f'Generated: {fobj.name}')

  

  if __name__ == "__main__":

      main()

file modified
+35 -41
@@ -29,78 +29,75 @@ 

  # cfg(all(unix, target_pointer_width = "32"))

  # cfg(not(foo))

  

- IDENT_CHARS = pp.alphas + "_", pp.alphanums + "_"

- 

+ IDENT_CHARS = pp.alphas + '_', pp.alphanums + '_'

  

  def _call(word, arg):

-     return pp.Group(pp.Literal(word) + pp.Suppress("(") + arg + pp.Suppress(")"))

- 

+     return pp.Group(pp.Literal(word) + pp.Suppress('(') + arg + pp.Suppress(')'))

  

  @functools.cache

  def cfg_grammar():

      pred = pp.Forward()

  

      ident = pp.Word(IDENT_CHARS[0], IDENT_CHARS[1])

-     option = pp.Group(ident + pp.Optional(pp.Suppress("=") + pp.quotedString))

+     option = pp.Group(ident + pp.Optional(pp.Suppress('=') + pp.quotedString))

  

-     not_ = _call("not", pred)

+     not_ = _call('not', pred)

  

      # pp.pyparsing_common.comma_separated_list?

      # any_ = _call('any', pp.pyparsing_common.comma_separated_list(pred))

      # all_ = _call('all', pp.pyparsing_common.comma_separated_list(pred))

      # all_ = _call('all', pp.delimited_list(pred))

  

-     any_ = _call("any", pred + pp.ZeroOrMore(pp.Suppress(",") + pred))

-     all_ = _call("all", pred + pp.ZeroOrMore(pp.Suppress(",") + pred))

+     any_ = _call('any', pred + pp.ZeroOrMore(pp.Suppress(',') + pred))

+     all_ = _call('all', pred + pp.ZeroOrMore(pp.Suppress(',') + pred))

  

      pred <<= not_ | any_ | all_ | option

  

-     grammar = _call("cfg", pred)

+     grammar = _call('cfg', pred)

      return grammar

  

- 

  @functools.cache

  def evaluate_predicate(name: str, value: str) -> bool:

      # based on: https://doc.rust-lang.org/reference/conditional-compilation.html

  

      match name:

-         case "target_arch":

+         case 'target_arch':

              # Needs to be ignored, as we cannot generate patches that are

              # different depending on the host architecture - except if the

-             # target architecture is "wasm32", which we don't support.

-             return value != "wasm32"

+             # target architecture is 'wasm32', which we don't support.

+             return value != 'wasm32'

  

-         case "target_feature":

-             # The "target_feature" predicate can be ignored as well, since the

+         case 'target_feature':

+             # The 'target_feature' predicate can be ignored as well, since the

              # valid values for this predicate are architecture-dependent.

              return True

  

-         case "target_os":

-             return value == "linux"

+         case 'target_os':

+             return value == 'linux'

  

-         case "target_family":

-             return value == "unix"

+         case 'target_family':

+             return value == 'unix'

  

-         case "target_env":

-             # The "target_env" predicate is used to disambiguate target

+         case 'target_env':

+             # The 'target_env' predicate is used to disambiguate target

              # platforms based on its C library / C ABI (i.e. we can ignore

-             # "msvc" and "musl"), and if there's no need to disambiguate, the

+             # 'msvc' and 'musl'), and if there's no need to disambiguate, the

              # value can be the empty string.

-             return value in ["", "gnu"]

+             return value in ['', 'gnu']

  

-         case "target_endian":

+         case 'target_endian':

              # Needs to be ignored, as we cannot generate patches that are

              # different depending on the host architecture.

              return True

  

-         case "target_pointer_width":

+         case 'target_pointer_width':

              # Needs to be ignored, as we cannot generate patches that are

              # different depending on the host architecture.

              return True

  

-         case "target_vendor":

-             # On linux systems, "target_vendor" is always "unknown".

-             return value == "unknown"

+         case 'target_vendor':

+             # On linux systems, 'target_vendor' is always 'unknown'.

+             return value == 'unknown'

  

          case _:

              log.warn(f'Ignoring invalid predicate \'"{name}" = "{value}"\' in cfg-expression.')
@@ -110,30 +107,28 @@ 

  @functools.cache

  def evaluate_atom(name: str) -> bool:

      match name:

-         case "unix":

+         case 'unix':

              return True

-         case "windows":

+         case 'windows':

              return False

          case _:

-             log.warn(

-                 f"Ignoring unknown identifier {name!r} in cfg-expression. "

-                 + 'Only "unix" and "windows" are standard identifiers, '

-                 + 'any non-standard "--cfg" flags are not supported.'

-             )

+             log.warn(f'Ignoring unknown identifier {name!r} in cfg-expression.'

+                      ' Only "unix" and "windows" are standard identifiers,'

+                      ' any non-standard "--cfg" flags are not supported.')

              return False

  

  

  def evaluate(expr, nested=False) -> bool:

-     if hasattr(expr, "asList"):

+     if hasattr(expr, 'asList'):

          expr = expr.asList()  # compat with pyparsing 2.7.x

      match expr:

-         case ["cfg", subexpr] if not nested:

+         case ['cfg', subexpr] if not nested:

              return evaluate(subexpr, True)

-         case ["not", subexpr] if nested:

+         case ['not', subexpr] if nested:

              return not evaluate(subexpr, True)

-         case ["all", *args] if nested:

+         case ['all', *args] if nested:

              return all(evaluate(arg, True) for arg in args)

-         case ["any", *args] if nested:

+         case ['any', *args] if nested:

              return any(evaluate(arg, True) for arg in args)

          case [variable, value] if nested:

              v = ast.literal_eval(value)
@@ -143,7 +138,6 @@ 

          case _:

              raise ValueError

  

- 

  def parse_and_evaluate(expr):

      parsed = cfg_grammar().parseString(expr)

      return evaluate(parsed[0])

file modified
+10 -7
@@ -10,7 +10,9 @@ 

  

  def _get_binaries(cargo_toml):

      manifest = Metadata.manifest(cargo_toml, check=False)

-     return [t["name"] for t in manifest.get("targets", []) if "bin" in t["kind"]]

+     return [

+         t['name'] for t in manifest.get('targets', []) if 'bin' in t['kind']

+     ]

  

  

  def _cargo_toml(source_path, path, exclude_vendor=True):
@@ -34,17 +36,18 @@ 

  

      # If path is already a Cargo.toml file, we are done

      binary_or_cargo_toml = os.path.basename(path)

-     if binary_or_cargo_toml == "Cargo.toml":

+     if binary_or_cargo_toml == 'Cargo.toml':

          return os.path.join(source_path, path)

  

-     cargo_tomls = glob.glob(os.path.join(source_path, "**/Cargo.toml"), recursive=True)

+     cargo_tomls = glob.glob(os.path.join(source_path, '**/Cargo.toml'),

+                             recursive=True)

      for cargo_toml in cargo_tomls:

-         if exclude_vendor and "vendor" in cargo_toml.split(os.sep):

+         if exclude_vendor and 'vendor' in cargo_toml.split(os.sep):

              continue

          if binary_or_cargo_toml in _get_binaries(cargo_toml):

              return cargo_toml

  

-     raise FileNotFoundError(f"Cargo.toml not found for binary {binary_or_cargo_toml}")

+     raise FileNotFoundError(f'Cargo.toml not found for binary {binary_or_cargo_toml}')

  

  

  def main():
@@ -94,7 +97,7 @@ 

              data.extend(md.provides(f) for f in features)

          if args.requires:

              # Someone should own /usr/share/cargo/registry

-             data.append("cargo")

+             data.append('cargo')

              if args.all_features:

                  data.extend(md.all_dependencies)

              else:
@@ -112,7 +115,7 @@ 

          if args.provides_vendor:

              # Print the vendoring providers only if the 'vendor'

              # directory is present

-             if args.vendor or os.path.isdir("vendor"):

+             if args.vendor or os.path.isdir('vendor'):

                  data.extend(md.resolved_dependencies())

          return data

  

file modified
+127 -115
@@ -8,51 +8,63 @@ 

  import subprocess

  from urllib.parse import urlparse

  

- Requirement = collections.namedtuple("Requirement", ("kind", "version"))

- Version = collections.namedtuple("Version", ("major", "minor", "patch", "pre_release", "build"))

+ 

+ Requirement = collections.namedtuple('Requirement', ('kind',

+                                                      'version'))

+ 

+ 

+ Version = collections.namedtuple('Version', ('major', 'minor',

+                                              'patch', 'pre_release',

+                                              'build'))

  

  

  class CargoSemVer:

      """Cargo semantic versioning parser"""

- 

-     KIND_ANY = "*"

-     KIND_LT = "<"

-     KIND_LTE = "<="

-     KIND_SHORTEQ = "="

-     KIND_EQUAL = "=="

-     KIND_EMPTY = ""

-     KIND_GTE = ">="

-     KIND_GT = ">"

-     KIND_NEQ = "!="

-     KIND_CARET = "^"

-     KIND_TILDE = "~"

-     KIND_COMPATIBLE = "~="

+     KIND_ANY = '*'

+     KIND_LT = '<'

+     KIND_LTE = '<='

+     KIND_SHORTEQ = '='

+     KIND_EQUAL = '=='

+     KIND_EMPTY = ''

+     KIND_GTE = '>='

+     KIND_GT = '>'

+     KIND_NEQ = '!='

+     KIND_CARET = '^'

+     KIND_TILDE = '~'

+     KIND_COMPATIBLE = '~='

  

      def __init__(self, requirement):

-         requirements = requirement.replace(" ", "").split(",")

+         requirements = requirement.replace(' ', '').split(',')

          self.requirements = [self.parse(i) for i in requirements]

-         self.normalized = [j for i in self.requirements for j in self.normalize(i)]

+         self.normalized = [j for i in self.requirements

+                            for j in self.normalize(i)]

  

      @staticmethod

      def parse(requirement):

          if not requirement:

-             raise ValueError(f"Invalid empty requirement " f"specification: {requirement}")

+             raise ValueError(f'Invalid empty requirement '

+                              f'specification: {requirement}')

  

-         match = re.match(r"^(?:([\d.\*]*\*))$|^(?:(<|<=|=|==|>=|>||!=|\^|~|~=)(\d.*))$", requirement)

+         match = re.match(

+             r'^(?:([\d.\*]*\*))$|^(?:(<|<=|=|==|>=|>||!=|\^|~|~=)(\d.*))$',

+             requirement)

          if not match:

-             raise ValueError(f"Invalid requirement " f"specification: {requirement}")

+             raise ValueError(f'Invalid requirement '

+                              f'specification: {requirement}')

  

          wildcard, kind, version = match.groups()

          if wildcard:

-             version = wildcard.replace(".*", "").replace("*", "")

+             version = wildcard.replace('.*', '').replace('*', '')

              kind = CargoSemVer.KIND_ANY

          return Requirement(kind, CargoSemVer.parse_version(version))

  

      @staticmethod

      def parse_version(version):

-         match = re.match(r"^(\d+)?(?:\.(\d+))?(?:\.(\d+))?(?:-([\w.-]+))?(?:\+([\w.-]+))?$", version)

+         match = re.match(

+             r'^(\d+)?(?:\.(\d+))?(?:\.(\d+))?(?:-([\w.-]+))?(?:\+([\w.-]+))?$',

+             version)

          if not match:

-             raise ValueError(f"Invalid version string: {version}")

+             raise ValueError(f'Invalid version string: {version}')

  

          major, minor, patch, pre_release, build = match.groups()

          major = int(major) if major else major
@@ -61,8 +73,9 @@ 

          return Version(major, minor, patch, pre_release, build)

  

      @staticmethod

-     def unparse_version(version, sep="-"):

-         version_str = f"{version.major}.{version.minor or 0}.{version.patch or 0}"

+     def unparse_version(version, sep='-'):

+         version_str = f'{version.major}.{version.minor or 0}' \

+             f'.{version.patch or 0}'

          if version.pre_release:

              version_str = f'{version_str}{sep}{version.pre_release.replace("-", "_")}'

          if version.build:
@@ -71,13 +84,11 @@ 

  

      @staticmethod

      def coerce(version):

-         return Version(

-             version.major or 0,

-             version.minor or 0,

-             version.patch or 0,

-             version.pre_release,

-             version.build,

-         )

+         return Version(version.major or 0,

+                        version.minor or 0,

+                        version.patch or 0,

+                        version.pre_release,

+                        version.build)

  

      @staticmethod

      def next_major(version):
@@ -105,7 +116,7 @@ 

          normalized = []

          kind, version = requirement

          if kind == CargoSemVer.KIND_NEQ:

-             raise ValueError(f"Kind not supported: {requirement}")

+             raise ValueError(f'Kind not supported: {requirement}')

  

          if kind == CargoSemVer.KIND_EQUAL:

              kind = CargoSemVer.KIND_SHORTEQ
@@ -115,22 +126,21 @@ 

              version = CargoSemVer.next_patch(version)

  

          if kind == CargoSemVer.KIND_ANY:

-             normalized.append((CargoSemVer.KIND_GTE, CargoSemVer.coerce(version)))

+             normalized.append((CargoSemVer.KIND_GTE,

+                                CargoSemVer.coerce(version)))

              if version.major is not None:

                  if version.minor is not None:

                      upper_version = CargoSemVer.next_minor(version)

                  else:

                      upper_version = CargoSemVer.next_major(version)

                  normalized.append((CargoSemVer.KIND_LT, upper_version))

-         elif kind in (

-             CargoSemVer.KIND_SHORTEQ,

-             CargoSemVer.KIND_GT,

-             CargoSemVer.KIND_GTE,

-             CargoSemVer.KIND_LT,

-             CargoSemVer.KIND_LTE,

-         ):

+         elif kind in (CargoSemVer.KIND_SHORTEQ,

+                       CargoSemVer.KIND_GT, CargoSemVer.KIND_GTE,

+                       CargoSemVer.KIND_LT, CargoSemVer.KIND_LTE):

              normalized.append((kind, coerced_version))

-         elif kind in (CargoSemVer.KIND_CARET, CargoSemVer.KIND_COMPATIBLE, CargoSemVer.KIND_EMPTY):

+         elif kind in (CargoSemVer.KIND_CARET,

+                       CargoSemVer.KIND_COMPATIBLE,

+                       CargoSemVer.KIND_EMPTY):

              if version.major == 0:

                  if version.minor is not None:

                      if version.minor != 0 or version.patch is None:
@@ -151,39 +161,37 @@ 

              normalized.append((CargoSemVer.KIND_GTE, coerced_version))

              normalized.append((CargoSemVer.KIND_LT, upper_version))

          else:

-             raise ValueError(f"Found unhandled kind: {requirement}")

+             raise ValueError(f'Found unhandled kind: {requirement}')

          return normalized

  

      @staticmethod

      def eval_(v1, op, v2):

          if op == CargoSemVer.KIND_SHORTEQ:

-             return all((v1.major == v2.major, v1.minor == v2.minor, v1.patch == v2.patch))

+             return all((v1.major == v2.major,

+                         v1.minor == v2.minor,

+                         v1.patch == v2.patch))

          elif op == CargoSemVer.KIND_GT:

-             return (

-                 (v1.major > v2.major)

-                 or (v1.major == v2.major and v1.minor > v2.minor)

-                 or (v1.major == v2.major and v1.minor == v2.minor and v1.patch > v2.patch)

-             )

+             return ((v1.major > v2.major) or

+                     (v1.major == v2.major and v1.minor > v2.minor) or

+                     (v1.major == v2.major and v1.minor == v2.minor and

+                      v1.patch > v2.patch))

          elif op == CargoSemVer.KIND_GTE:

-             return (

-                 (v1.major >= v2.major)

-                 or (v1.major == v2.major and v1.minor >= v2.minor)

-                 or (v1.major == v2.major and v1.minor == v2.minor and v1.patch >= v2.patch)

-             )

+             return ((v1.major >= v2.major) or

+                     (v1.major == v2.major and v1.minor >= v2.minor) or

+                     (v1.major == v2.major and v1.minor == v2.minor and

+                      v1.patch >= v2.patch))

          elif op == CargoSemVer.KIND_LT:

-             return (

-                 (v1.major < v2.major)

-                 or (v1.major == v2.major and v1.minor < v2.minor)

-                 or (v1.major == v2.major and v1.minor == v2.minor and v1.patch < v2.patch)

-             )

+             return ((v1.major < v2.major) or

+                     (v1.major == v2.major and v1.minor < v2.minor) or

+                     (v1.major == v2.major and v1.minor == v2.minor and

+                      v1.patch < v2.patch))

          elif op == CargoSemVer.KIND_LTE:

-             return (

-                 (v1.major <= v2.major)

-                 or (v1.major == v2.major and v1.minor <= v2.minor)

-                 or (v1.major == v2.major and v1.minor == v2.minor and v1.patch <= v2.patch)

-             )

+             return ((v1.major <= v2.major) or

+                     (v1.major == v2.major and v1.minor <= v2.minor) or

+                     (v1.major == v2.major and v1.minor == v2.minor and

+                      v1.patch <= v2.patch))

          else:

-             raise ValueError(f"Cannot evaluate operator: {op}")

+             raise ValueError(f'Cannot evaluate operator: {op}')

  

  

  class Target:
@@ -196,7 +204,8 @@ 

  

  

  class Dependency:

-     def __init__(self, name, req=None, features=(), optional=False, bundled=False):

+     def __init__(self, name, req=None, features=(), optional=False,

+                  bundled=False):

          self.name = name

          self.req = req

          self.features = features
@@ -208,12 +217,10 @@ 

          features = set(metadata["features"])

          if metadata["uses_default_features"]:

              features.add("default")

-         kwargs = {

-             "name": metadata["name"],

-             "req": metadata["req"],

-             "optional": metadata["optional"],

-             "features": features,

-         }

+         kwargs = {"name": metadata["name"],

+                   "req": metadata["req"],

+                   "optional": metadata["optional"],

+                   "features": features}

          return cls(**kwargs)

  

      @staticmethod
@@ -224,10 +231,9 @@ 

              cap = f"bundled({cap})"

          if not reqs:

              return cap

-         deps = " with ".join(

+         deps = ' with '.join(

              f'{cap} {op} {CargoSemVer.unparse_version(version, sep="~")}{"~" if op == CargoSemVer.KIND_LT else ""}'

-             for op, version in reqs

-         )

+             for op, version in reqs)

          if len(reqs) > 1:

              return f"({deps})"

          else:
@@ -235,10 +241,9 @@ 

  

      def normalize(self):

          semver = CargoSemVer(self.req)

-         return [

-             self._apply_reqs(self.name, semver.normalized, feature, self.bundled)

-             for feature in self.features or (None,)

-         ]

+         return [self._apply_reqs(self.name, semver.normalized, feature,

+                                  self.bundled)

+                 for feature in self.features or (None,)]

  

      def __repr__(self):

          features = sorted(feature for feature in self.features if feature)
@@ -279,28 +284,23 @@ 

          if description is None:

              self._description = self._summary = None

              return

-         description = description.replace("\n\n", "\r").replace("\n", " ").replace("\r", "\n").strip()

-         description = re.sub(

-             rf"^(?:{self.name}|This(?:\s+\w+)?)(?:\s*,|\s+is|\s+provides)\s+",

-             "",

-             description,

-             flags=re.I,

-         )

-         description = re.sub(r"^(?:a|an|the)\s+", "", description, flags=re.I)

-         description = f"{description[0].upper()}{description[1:]}"

-         if description[-1] != ".":

-             description = f"{description}."

- 

-         p1 = description.find(".")

-         p2 = description.find(".\n")

+         description = description.replace('\n\n', '\r').replace('\n', ' ').replace('\r', '\n').strip()

+         description = re.sub(rf'^(?:{self.name}|This(?:\s+\w+)?)(?:\s*,|\s+is|\s+provides)\s+', '', description, flags=re.I)

+         description = re.sub(r'^(?:a|an|the)\s+', '', description, flags=re.I)

+         description = f'{description[0].upper()}{description[1:]}'

+         if description[-1] != '.':

+             description = f'{description}.'

+ 

+         p1 = description.find('.')

+         p2 = description.find('.\n')

          if p2 != -1:

              p1 = max(p1, p2)

          else:

              p1 = len(description) - 1

-         p2 = description.find(". ")

+         p2 = description.find('. ')

          if p2 != -1:

              p1 = min(p1, p2)

-         p2 = description.find("\n")

+         p2 = description.find('\n')

          if p2 != -1:

              p = min(p1, p2)

          else:
@@ -332,7 +332,9 @@ 

          # c.f. https://pagure.io/fedora-rust/rust2rpm/issue/186

  

          deps_by_feature = {}

-         local_features = set(md["features"]) | set(d["rename"] for d in md["dependencies"] if d["rename"] is not None)

+         local_features = set(md["features"]) | set(

+             d["rename"] for d in md["dependencies"] if d["rename"] is not None

+         )

          for feature, f_deps in md["features"].items():

              features = {None}

              deps = set()
@@ -364,9 +366,12 @@ 

              deps_by_feature["default"] = ({None}, set())

  

          self.dependencies = deps_by_feature

-         self.dev_dependencies = {Dependency.from_json(dep) for dep in md["dependencies"] if dep["kind"] == "dev"}

+         self.dev_dependencies = {Dependency.from_json(dep)

+                                  for dep in md["dependencies"]

+                                  if dep["kind"] == "dev"}

  

-         self.targets = {Target(tgt["name"], tgt["kind"][0]) for tgt in md["targets"]}

+         self.targets = {Target(tgt["name"], tgt["kind"][0])

+                         for tgt in md["targets"]}

  

          return self

  
@@ -374,14 +379,17 @@ 

      def from_file(cls, path, include_members=False):

          instances = []

          members = Metadata.members(path) if include_members else []

-         for member in members or [path]:

+         for member in (members or [path]):

              instance = cls.from_json(Metadata.manifest(member), member)

              instances.append(instance)

          return instances

  

      @staticmethod

      def manifest(path, check=True):

-         output = subprocess.run(["cargo", "read-manifest", f"--manifest-path={path}"], check=check, capture_output=True)

+         output = subprocess.run(

+             ["cargo", "read-manifest", f"--manifest-path={path}"],

+             check=check, capture_output=True

+         )

          try:

              result = json.loads(output.stdout)

          except json.decoder.JSONDecodeError:
@@ -392,7 +400,8 @@ 

  

      @staticmethod

      def metadata(path, deps=False):

-         cmd = ["cargo", "metadata", "--format-version=1", f"--manifest-path={path}"]

+         cmd = ["cargo", "metadata", "--format-version=1",

+                f"--manifest-path={path}"]

          if not deps:

              cmd.append("--no-deps")

          return json.loads(subprocess.check_output(cmd))
@@ -401,9 +410,9 @@ 

      def members(path):

          members = []

          metadata = Metadata.metadata(path)

-         for workspace in metadata.get("workspace_members", []):

-             path = re.search(r"\((.*)\)", workspace).group(1)

-             members.append(os.path.join(urlparse(path).path, "Cargo.toml"))

+         for workspace in metadata.get('workspace_members', []):

+             path = re.search(r'\((.*)\)', workspace).group(1)

+             members.append(os.path.join(urlparse(path).path, 'Cargo.toml'))

          return members

  

      @property
@@ -433,13 +442,14 @@ 

              return self._resolve(self.dependencies, feature)[1]

          else:

              features, deps = self.dependencies[feature]

-             fdeps = set(Dependency(self.name, f"={self._version}", features={feature}) for feature in features)

+             fdeps = set(Dependency(self.name, f"={self._version}", features={feature})

+                         for feature in features)

              return fdeps | deps

  

      @staticmethod

      def _match_crate(dependency, metadata):

-         for crate in metadata["resolve"]["nodes"]:

-             name, version, _ = crate["id"].split()

+         for crate in metadata['resolve']['nodes']:

+             name, version, _ = crate['id'].split()

              if name != dependency.name:

                  continue

              v1 = CargoSemVer.parse_version(version)
@@ -449,8 +459,8 @@ 

  

      @staticmethod

      def _find_crate(dependency, metadata):

-         for crate in metadata["resolve"]["nodes"]:

-             if dependency == crate["id"]:

+         for crate in metadata['resolve']['nodes']:

+             if dependency == crate['id']:

                  return crate

  

      @staticmethod
@@ -472,28 +482,30 @@ 

          for dep in dependencies:

              crate = Metadata._match_crate(dep, metadata)

              if not crate:

-                 raise ValueError(f"Cannot find crate for {dep}")

+                 raise ValueError(f'Cannot find crate for {dep}')

              closure.append(crate)

  

          # Close over the initial packages

          for crate in closure:

-             for dep in crate["dependencies"]:

+             for dep in crate['dependencies']:

                  crate = Metadata._find_crate(dep, metadata)

                  if not crate:

-                     raise ValueError(f"Cannot find crate for {dep}")

+                     raise ValueError(f'Cannot find crate for {dep}')

                  if crate not in closure:

                      closure.append(crate)

  

          # Transform the crate information to a dependency

          dependencies = []

          for crate in closure:

-             name, version, _ = crate["id"].split()

-             dependencies.append(Dependency(name, f"={version}", crate["features"] or ("default",), bundled=True))

+             name, version, _ = crate['id'].split()

+             dependencies.append(Dependency(name, f'={version}',

+                                            crate['features'] or ('default',),

+                                            bundled=True))

          return dependencies

  

      def resolved_dependencies(self, feature=None):

          if not self._path:

-             raise ValueError("Metadata instance without Cargo.toml associated")

+             raise ValueError('Metadata instance without Cargo.toml associated')

  

          initial_deps = self._resolve(self.dependencies, feature)[1]

          metadata = Metadata.metadata(self._path, deps=True)

file modified
+63 -69
@@ -5,45 +5,39 @@ 

  from . import __version__, licensing

  from .core import metadata

  

- 

  def to_list(s):

      if not s:

          return []

      return list(filter(None, (l.strip() for l in s.splitlines())))

  

- 

  def spec_file_template():

      env = jinja2.Environment(

-         loader=jinja2.ChoiceLoader(

-             [

-                 jinja2.FileSystemLoader(["/"]),

-                 jinja2.PackageLoader("rust2rpm", "templates"),

-             ]

-         ),

-         extensions=["jinja2.ext.do"],

+         loader=jinja2.ChoiceLoader([

+             jinja2.FileSystemLoader(['/']),

+             jinja2.PackageLoader('rust2rpm', 'templates'),

+         ]),

+         extensions=['jinja2.ext.do'],

          trim_blocks=True,

-         lstrip_blocks=True,

-     )

- 

-     env.globals["normalize_deps"] = metadata.normalize_deps

-     env.globals["to_list"] = to_list

+         lstrip_blocks=True)

  

-     return env.get_template("main.spec")

+     env.globals['normalize_deps'] = metadata.normalize_deps

+     env.globals['to_list'] = to_list

  

+     return env.get_template('main.spec')

  

  def spec_file_render(

-     args,

-     pkg_name,

-     crate,

-     metadata,

-     patch_file_manual,

-     patch_file_automatic,

-     packager,

-     doc_files,

-     license_files,

-     distconf,

-     all_features,

-     date=None,

+         args,

+         pkg_name,

+         crate,

+         metadata,

+         patch_file_manual,

+         patch_file_automatic,

+         packager,

+         doc_files,

+         license_files,

+         distconf,

+         all_features,

+         date=None,

  ):

      template = spec_file_template()

  
@@ -53,57 +47,58 @@ 

      is_lib = len(libs) > 0

  

      kwargs = {

-         "generator_version": __version__,

-         "target": args.target,

-         "crate": crate,

-         "include_devel": is_lib,

-         "pkg_name": pkg_name,

-         "auto_changelog_entry": args.auto_changelog_entry,

-         "rpmautospec": args.rpmautospec,

-         "relative_license_paths": args.relative_license_paths,

-         "generate_buildrequires": args.dynamic_buildrequires,

-         "doc_files": doc_files,

-         "license_files": license_files,

-         "distconf": distconf,

-         "all_features": all_features,

+         'generator_version': __version__,

+         'target': args.target,

+         'crate': crate,

+         'include_devel': is_lib,

+         'pkg_name': pkg_name,

+         'auto_changelog_entry': args.auto_changelog_entry,

+         'rpmautospec': args.rpmautospec,

+         'relative_license_paths': args.relative_license_paths,

+         'generate_buildrequires': args.dynamic_buildrequires,

+         'doc_files': doc_files,

+         'license_files': license_files,

+         'distconf': distconf,

+         'all_features': all_features,

      }

  

      if is_bin:

-         kwargs["include_main"] = True

-         kwargs["bins"] = bins

+         kwargs['include_main'] = True

+         kwargs['bins'] = bins

      elif is_lib:

-         kwargs["include_main"] = False

+         kwargs['include_main'] = False

      else:

-         raise ValueError("No bins and no libs")

- 

-     if args.target in {"fedora", "mageia", "opensuse"}:

-         kwargs["include_build_requires"] = True

-         kwargs["include_provides"] = False

-         kwargs["include_requires"] = False

-     elif args.target == "plain":

-         kwargs["include_build_requires"] = True

-         kwargs["include_provides"] = True

-         kwargs["include_requires"] = True

+         raise ValueError('No bins and no libs')

+ 

+     if args.target in {'fedora', 'mageia', 'opensuse'}:

+         kwargs['include_build_requires'] = True

+         kwargs['include_provides'] = False

+         kwargs['include_requires'] = False

+     elif args.target == 'plain':

+         kwargs['include_build_requires'] = True

+         kwargs['include_provides'] = True

+         kwargs['include_requires'] = True

      else:

-         assert False, f"Unknown target {args.target!r}"

- 

-     if args.target == "mageia":

-         kwargs["pkg_release"] = "%mkrel 1"

-         kwargs["rust_group"] = "Development/Rust"

-     elif args.target == "opensuse":

-         kwargs["spec_copyright_year"] = time.strftime("%Y")

-         kwargs["pkg_release"] = "0"

-         kwargs["rust_group"] = "Development/Libraries/Rust"

+         assert False, f'Unknown target {args.target!r}'

+ 

+     if args.target == 'mageia':

+         kwargs['pkg_release'] = '%mkrel 1'

+         kwargs['rust_group'] = 'Development/Rust'

+     elif args.target == 'opensuse':

+         kwargs['spec_copyright_year'] = time.strftime('%Y')

+         kwargs['pkg_release'] = '0'

+         kwargs['rust_group'] = 'Development/Libraries/Rust'

      elif args.rpmautospec:

-         kwargs["pkg_release"] = "%autorelease"

+         kwargs['pkg_release'] = '%autorelease'

      else:

-         kwargs["pkg_release"] = "1%{?dist}"

+         kwargs['pkg_release'] = '1%{?dist}'

  

-     time_args = ["%a %b %d %T %Z %Y" if args.target in {"opensuse"} else "%a %b %d %Y"] + ([date] if date else [])

-     kwargs["date"] = time.strftime(*time_args)

+     time_args = (['%a %b %d %T %Z %Y' if args.target in {'opensuse'} else '%a %b %d %Y'] +

+                  ([date] if date else []))

+     kwargs['date'] = time.strftime(*time_args)

  

      if packager is not None:

-         kwargs["packager"] = packager

+         kwargs['packager'] = packager

  

      if metadata.license is not None:

          license, comments = licensing.translate_license(args.target, metadata.license)
@@ -114,8 +109,7 @@ 

          metadata=metadata,

          patch_file_manual=patch_file_manual,

          patch_file_automatic=patch_file_automatic,

-         **kwargs,

-     )

+         **kwargs)

  

      if not spec_contents.endswith("\n"):

          spec_contents += "\n"

file modified
+19 -28
@@ -4,65 +4,56 @@ 

  

  from . import log

  

- SPDX_TO_FEDORA_CSV = os.path.dirname(__file__) + "/spdx_to_fedora.csv"

- 

+ SPDX_TO_FEDORA_CSV = os.path.dirname(__file__) + '/spdx_to_fedora.csv'

  

  def translate_slashes(license):

      "Replace all slashes with OR, emit warning"

      split = [l.strip() for l in license.split("/")]

      if len(split) > 1:

          log.info('Upstream uses deprecated "/" syntax. Replacing with "OR"')

-     return " OR ".join(split)

- 

+     return ' OR '.join(split)

  

  @functools.lru_cache()

  def spdx_to_fedora_map():

-     with open(SPDX_TO_FEDORA_CSV, newline="") as f:

+     with open(SPDX_TO_FEDORA_CSV, newline='') as f:

          reader = csv.DictReader(f)

-         return {

-             line["SPDX License Identifier"]: line["Fedora Short Name"]

-             for line in reader

-             if line["SPDX License Identifier"]

-         }

- 

+         return {line['SPDX License Identifier']: line['Fedora Short Name']

+                 for line in reader

+                 if line['SPDX License Identifier']}

  

  def dump_sdpx_to_fedora_map(file):

      for k, v in spdx_to_fedora_map().items():

          print(f"{k} → {v}", file=file)

  

- 

  def translate_license_fedora(license):

      comments = []

      final = []

      for tag in license.split():

          # We accept all variant cases, but output lowercase which is what Fedora LicensingGuidelines specify

-         if tag.upper() == "OR":

-             final.append("or")

-         elif tag.upper() == "AND":

-             final.append("and")

+         if tag.upper() == 'OR':

+             final.append('or')

+         elif tag.upper() == 'AND':

+             final.append('and')

          else:

-             if tag.endswith("+"):

-                 key = tag[:-1] + "-or-later"

-                 fulltag = f"{tag} ({key})"

+             if tag.endswith('+'):

+                 key = tag[:-1] + '-or-later'

+                 fulltag = f'{tag} ({key})'

              else:

                  key = fulltag = tag

  

              mapped = spdx_to_fedora_map().get(key, None)

              if mapped is None:

-                 comments += [f"# FIXME: Upstream uses unknown SPDX tag {fulltag}!"]

+                 comments += [f'# FIXME: Upstream uses unknown SPDX tag {fulltag}!']

                  final.append(tag)

-             elif mapped == "":

-                 comments += [

-                     f"# FIXME: Upstream SPDX tag {fulltag} not listed in Fedora's good licenses list.",

-                     "# FIXME: This package might not be allowed in Fedora!",

-                 ]

+             elif mapped == '':

+                 comments += [f"# FIXME: Upstream SPDX tag {fulltag} not listed in Fedora's good licenses list.",

+                              "# FIXME: This package might not be allowed in Fedora!"]

                  final.append(tag)

              else:

                  final.append(mapped)

                  if mapped != tag:

-                     log.info(f"Upstream license tag {fulltag!r} translated to {mapped!r}.")

-     return (" ".join(final), "\n".join(comments) or None)

- 

+                     log.info(f'Upstream license tag {fulltag!r} translated to {mapped!r}.')

+     return (' '.join(final), '\n'.join(comments) or None)

  

  def translate_license(target, license):

      license = translate_slashes(license)

file modified
+1 -1
@@ -15,7 +15,7 @@ 

  

  

  def _wrap(message, prefix):

-     return textwrap.wrap(message, 80, initial_indent=f"{prefix} ", subsequent_indent=" " * (len(prefix) + 1))

+     return textwrap.wrap(message, 80, initial_indent=f"{prefix} ", subsequent_indent=" "*(len(prefix) + 1))

  

  

  def success(message):

file modified
+16 -19
@@ -2,35 +2,32 @@ 

  

  from rust2rpm import cfg

  

- 

  def test_pyparsing_run_tests():

      g = cfg.cfg_grammar()

  

-     g.runTests(

-         """\

-         cfg(target_os = "macos")

-         cfg(any(foo, bar))

-         cfg(all(unix, target_pointer_width = "32"))

-         cfg(not(foo))

-         """

-     )

+     g.runTests("""\

+     cfg(target_os = "macos")

+     cfg(any(foo, bar))

+     cfg(all(unix, target_pointer_width = "32"))

+     cfg(not(foo))

+     """)

  

  

  @pytest.mark.parametrize(

      "expr, expected",

      [

          ('cfg(target_os = "macos")', False),

-         ("cfg(any(foo, bar))", False),

+         ('cfg(any(foo, bar))', False),

          ('cfg(all(unix, target_pointer_width = "16"))', True),

-         ("cfg(not(foo))", True),

-         ("cfg(unix)", True),

-         ("cfg(not(unix))", False),

-         ("cfg(windows)", False),

-         ("cfg(linux)", False),  # not defined

-         ("cfg(not(windows))", True),

-         ("cfg(any(unix, windows))", True),

-         ("cfg(any(windows, unix))", True),

-         ("cfg(any(windows, windows, windows))", False),

+         ('cfg(not(foo))', True),

+         ('cfg(unix)', True),

+         ('cfg(not(unix))', False),

+         ('cfg(windows)', False),

+         ('cfg(linux)', False),  # not defined

+         ('cfg(not(windows))', True),

+         ('cfg(any(unix, windows))', True),

+         ('cfg(any(windows, unix))', True),

+         ('cfg(any(windows, windows, windows))', False),

          ('cfg(target_os = "linux")', True),

          ('cfg(any(target_os = "linux"))', True),

          ('cfg(all(target_os = "linux"))', True),

@@ -7,14 +7,18 @@ 

  import pytest

  

  from rust2rpm.generator import to_list, spec_file_render

- from rust2rpm.__main__ import Metadata, get_parser, package_name_suffixed, drop_foreign_dependencies

+ from rust2rpm.__main__ import (

+     Metadata,

+     get_parser,

+     package_name_suffixed,

+     drop_foreign_dependencies)

  

  

  def test_to_list():

-     assert to_list("1\n2") == ["1", "2"]

-     assert to_list("1\n\n   2") == ["1", "2"]

-     assert to_list("   2   ") == ["2"]

-     assert to_list("\n\n") == []

+     assert to_list('1\n2') == ['1', '2']

+     assert to_list('1\n\n   2'   ) == ['1', '2']

+     assert to_list('   2   ') == ['2']

+     assert to_list('\n\n') == []

  

  

  # How to add new tests samples:
@@ -27,56 +31,59 @@ 

  

  FIXED_DATE = time.gmtime(12345)

  

- tomlfiles = [p for p in resources.files("rust2rpm.tests.samples").iterdir() if p.suffix == ".toml"]

- 

+ tomlfiles = [p

+              for p in resources.files('rust2rpm.tests.samples').iterdir()

+              if p.suffix == '.toml']

  

  def mock_spec_file_render(crate, tomlfile, target, tmpdir):

      tmpdir = pathlib.Path(tmpdir)

      # sadly we need to do this because cargo insists on looking for files

-     tmpdir.joinpath("src").mkdir()

-     tmpdir.joinpath("src/lib.rs").write_text("# hello!")

-     tmpdir.joinpath("src/main.rs").write_text("# hello!")

+     tmpdir.joinpath('src').mkdir()

+     tmpdir.joinpath('src/lib.rs').write_text('# hello!')

+     tmpdir.joinpath('src/main.rs').write_text('# hello!')

  

-     args = get_parser().parse_args(["foobar", f"--target={target}", "-a" if target == "fedora" else "--no-rpmautospec"])

+     args = get_parser().parse_args(['foobar',

+                                     f'--target={target}',

+                                     '-a' if target == 'fedora' else '--no-rpmautospec'])

      pkg_name = package_name_suffixed(crate, args.suffix)

  

      toml_before = open(tomlfile).readlines()

      toml_after = drop_foreign_dependencies(toml_before) or toml_before

  

-     fake_toml = tmpdir / "Cargo.toml"

-     fake_toml.write_text("\n".join(toml_after))

+     fake_toml = tmpdir / 'Cargo.toml'

+     fake_toml.write_text('\n'.join(toml_after))

  

-     (metadata,) = Metadata.from_file(fake_toml)

+     metadata, = Metadata.from_file(fake_toml)