-
-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[email protected]: migrate aliases #87075
Conversation
Not sure this is ready yet, as |
0c9e4c8
to
048bec3
Compare
Sorry, when I said this isn't ready because We should wait until most/all Python-dependent formulae have been migrated to |
I fully understand that. I pushed more commits here and we can merge these changes in a single PR when we are ready (maybe 2 weeks later). |
Oh, the review is not requested by me. We are probably not ready for this yet. The migration for |
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
The migration process for $ git rev-parse HEAD # current HEAD
ec64d6dd8537b662ecb84a500508a89aa12e77fe
$ for formula in $(find Formula -name 'python@*.rb' | xargs basename -s .rb | sort -rV); do echo "$(grep -rlF 'depends_on "'"${formula}"'"' Formula | wc -l)\tformulae depend on ${formula}"; done
268 formulae depend on [email protected]
335 formulae depend on [email protected]
11 formulae depend on [email protected]
3 formulae depend on [email protected]
$ git checkout a4d29eb6431ac9b57f07d6b29f3c5a1238ef2370
Note: switching to 'a4d29eb6431ac9b57f07d6b29f3c5a1238ef2370'.
HEAD is now at a4d29eb6431 [email protected]: migrate aliases
$ for formula in $(find Formula -name 'python@*.rb' | xargs basename -s .rb | sort -rV); do echo "$(grep -rlF 'depends_on "'"${formula}"'"' Formula | wc -l)\tformulae depend on ${formula}"; done
425 formulae depend on [email protected]
22 formulae depend on [email protected]
5 formulae depend on [email protected] |
I wouldn't count on the remaining migration being completed in three weeks. It might, but I also think it'll take longer than the first batch of formulae that's been migrated, since most of the remaining formulae to be migrated live in a few large dependency trees that need to be migrated together. That will take some work. |
Not that much movement in the past ten days. |
a03cbbc
to
6ca43aa
Compare
Any updates? It has been two months since Python 3.10 was released. |
Running the script now gives 10 more formula on 3.10. You can't just wait here, if you want this to happen soon you'll need to help migrate them.
|
Please add label: python-3.10-migration so that those who want to help get to Python 3.10 know how to discover which formulae to work on. |
I think we could open an issue to track the progress of the Python 3.10 migration process. Should we migrate formula-by-formula in a single pull request or migrate bunch of formulae in a single pull request (test them at once)? |
This comment has been minimized.
This comment has been minimized.
It's not quite that simple, since dependency trees need to be migrated together. See #87277 |
UPDATE: There are 7 pull requests needed in total:
HEAD: d99ad28
Python code to produce: #!/usr/bin/env python3
# %%
import json
import shutil
from collections import defaultdict, deque
from subprocess import check_output, run, DEVNULL, PIPE
from typing import OrderedDict
from toposort import toposort # pip install toposort
brew = shutil.which('brew')
assert brew is not None, 'Could not find `brew` executable in PATH.'
git = shutil.which('git')
assert git is not None, 'Could not find `git` executable in PATH'
HOMEBREW_CORE_REPOSITORY = check_output([brew, '--repository', 'homebrew/core']).decode().strip()
HEAD = check_output([git, '-C', HOMEBREW_CORE_REPOSITORY, 'rev-parse', 'HEAD']).decode().strip()
print(f'brew: {brew}')
print(f'git: {git}')
print(f'HEAD: {HEAD}')
# %%
def brew_uses(formula):
# Directly call `brew uses ...` is too slow
# Use `grep` command instead
files = run(['grep', '-rlF', f'depends_on "{formula}"'],
cwd=f'{HOMEBREW_CORE_REPOSITORY}/Formula',
stdout=PIPE, stderr=DEVNULL).stdout.decode().split()
return sorted(map(lambda rubyfile: rubyfile[:-3], files))
ALL_FORMULAE = brew_uses('[email protected]')
ALL_FORMULAE.remove('[email protected]')
ALL_FORMULAE_SET = set(ALL_FORMULAE)
USES = dict()
DEPENDENCIES = {formula: set() for formula in ALL_FORMULAE}
for formula in ALL_FORMULAE:
USES[formula] = sorted(set(brew_uses(formula)) & ALL_FORMULAE_SET)
for downstream in USES[formula]:
DEPENDENCIES[downstream].add(formula)
# %%
def flatten(nested):
flattened = []
for item in nested:
if not isinstance(item, str) and hasattr(nested, '__iter__'):
flattened.extend(flatten(item))
else:
flattened.append(item)
return flattened
def topo_order(dependencies):
# Topological sort (in the same level, sort by number of downstream nodes)
return list(map(lambda fl: sorted(fl, key=lambda f: len(USES[f]), reverse=True), toposort(dependencies)))
def topo_depends(formula):
dependencies = defaultdict(set)
q = deque([formula])
q.extend(USES[formula])
q.extend(DEPENDENCIES[formula])
while q:
f = q.popleft()
if f in dependencies:
continue
dependencies[f] = DEPENDENCIES[f]
q.extend(USES[f])
q.extend(DEPENDENCIES[f])
return topo_order(dependencies)
families = []
family_roots = set(topo_order(DEPENDENCIES)[0])
while family_roots:
root = family_roots.pop()
family = topo_depends(root)
family_roots.difference_update(family[0])
families.append(family)
# %%
results = OrderedDict({'stand-alones': []})
for family in sorted(families, key=lambda family: (len(flatten(family)), family[0][0])):
family_flattened = flatten(family)
n_formulae = len(family_flattened)
if len(family_flattened) > 1:
roots = family[0]
results[roots[0]] = family
else:
results['stand-alones'].extend(family_flattened)
results['stand-alones'] = [results['stand-alones']]
# %%
for i, (root, family) in enumerate(results.items(), start=1):
family_flattened = flatten(family)
n_formulae = len(family_flattened)
print()
print(f'- **{i}. Family `{root}` ({n_formulae} {"formulae" if n_formulae > 1 else "formula"})**')
print()
if root == 'stand-alones':
for formula in family_flattened:
print(f' - [ ] `{formula}`')
else:
print(f' ```')
print(f' {family}')
print(f' ```')
# %%
with open('families.json', 'wt') as file:
json.dump(results, file, indent=2) |
CI tap syntax has passed. No more conflict in the dependency trees. $ git rev-parse HEAD
40171bc81d27ffbd0c53e5503f57365c4d901670
$ for formula in $(find Formula -name 'python@*.rb' | xargs basename -s .rb | sort -rV); do echo "$(grep -rlF 'depends_on "'"${formula}"'"' Formula | wc -l)\tformulae depend on ${formula}"; done
599 formulae depend on [email protected]
103 formulae depend on [email protected]
9 formulae depend on [email protected]
2 formulae depend on [email protected] |
Implemented this at #107517. |
Since depends_on "[email protected]"
python = Formula["[email protected]"].bin/"python3" or depends_on "[email protected]"
python = which("python3") There are bunch of formulae need to add If we make a symlink |
For those formulae in particular: There aren't too many of those. I count less than 35. But it is not necessary to fix them all in the same PR. Some alternatives:
The second doesn't completely fix the ones that look for Of course, there could be many more formulae that assume [*] This is also useful for the formulae that still have both |
Require 91 + 38 + 28 separate PRs to add $ for formula in $(find Formula -name 'python@*.rb' | xargs basename -s .rb | sort -rV); do echo "$(grep -rlF 'Formula["'"${formula}"'"].opt_bin' Formula | wc -l)\tformulae use python3 in ${formula}'s opt_bin"; done
91 formulae use python3 in [email protected]'s opt_bin
38 formulae use python3 in [email protected]'s opt_bin
0 formulae use python3 in [email protected]'s opt_bin
0 formulae use python3 in [email protected]'s opt_bin
$ grep -rlF 'which("python3")' Formula | wc -l
28 It would be good to handle this in We can also add new attributes to def python3
bin/"python#{version.major_minor}"
end
def python
bin/"python#{version.major_minor}"
end Then in the dependent: -python = Formula["[email protected]"].bin/"python3"
+python = Formula["[email protected]"].python3 I think all of these may be out of the scope about migrating alias. Although |
8a1a03c
to
6ee7709
Compare
6ee7709
to
51a5652
Compare
This makes sure that Python does not install major-versioned files (e.g. `python3`, `python3-config`) and instead only installs files with both a major and minor version (e.g. `python3.9`, `python3.9-config`). This will allow us to have multiple versions of Python linked into `HOMEBREW_PREFIX` without conflicts. If users want to call `python3.9` as `python3`, then they can add `libexec/"bin"` to their `PATH`. Going forward, this will help simplify migrating to newer versions of Python, since we will not need to make the newer version keg-only while dependent formulae are migrated. See discussion at Homebrew/discussions#2776, and documentation at https://github.com/python/cpython#installing-multiple-versions Closes Homebrew#87075.
Thanks for your help with pushing the migration, @XuehaiPan. |
brew install --build-from-source <formula>
, where<formula>
is the name of the formula you're submitting?brew test <formula>
, where<formula>
is the name of the formula you're submitting?brew audit --strict <formula>
(after doingbrew install --build-from-source <formula>
)? If this is a new formula, does it passbrew audit --new <formula>
?Migrate aliases (
python
,python3
,python@3
) to[email protected]
.