From 308d7f7b9832e6d14d29f3475d2945efdfc77358 Mon Sep 17 00:00:00 2001 From: Nathan Dunfield Date: Sun, 13 Aug 2023 21:05:05 -0500 Subject: [PATCH 1/5] Fix to Triangulation -> Link -> Triangulation reversing orientation If a Triangulation is specified by a DT code *with flips*, then one could *sometimes* change the orientation of the exterior by what should have been a no-op:: >>> E0 = snappy.Manifold('DT[eaebdeac.11100]') >>> E0.chern_simons() 0.153204133297152 >>> E0.link().exterior().chern_simons() -0.153204133297152 This only happened in certain circumstances, and the DT codes in HTLinkExteriors were seemingly immune. This bug had the same root cause as dd9a2e7f0ed8db. --- cython/core/triangulation.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cython/core/triangulation.pyx b/cython/core/triangulation.pyx index 7d9e54d31..2eb2207a1 100644 --- a/cython/core/triangulation.pyx +++ b/cython/core/triangulation.pyx @@ -352,7 +352,7 @@ cdef class Triangulation(): if self._PDcode is not None: return spherogram.Link(self._PDcode) elif self.DT_code() is not None: - return spherogram.DTcodec(self.DT_code()).link() + return spherogram.DTcodec(*self.DT_code(flips=True)).link() else: raise ValueError('No associated link known.') From 35d04d81f018a67f0485cf136d2f16babeaa9423 Mon Sep 17 00:00:00 2001 From: Nathan Dunfield Date: Mon, 14 Aug 2023 09:41:23 -0500 Subject: [PATCH 2/5] CI: pin version of cibuildwheel, skip Python 3.12 for now --- .cirrus.yml | 4 ++-- .github/workflows/linux.yml | 16 +++------------- .github/workflows/macos.yml | 16 +++------------- .github/workflows/windows.yml | 18 ++++-------------- 4 files changed, 12 insertions(+), 42 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 8709894d1..9ebea004a 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -4,7 +4,7 @@ cirrus_wheels_macos_arm64_task: image: ghcr.io/cirruslabs/macos-ventura-xcode:latest env: CIBW_ARCHS_MACOS: arm64 - CIBW_SKIP: pp* cp38* + CIBW_SKIP: pp* cp38* cp312* CIBW_BEFORE_BUILD: > pip install cython FXrays low_index sphinx sphinx_rtd_theme && pip install --pre --extra-index-url https://test.pypi.org/simple cypari && @@ -22,7 +22,7 @@ cirrus_wheels_macos_arm64_task: - brew install python3 - python3 --version install_cibuildwheel_script: - - python3 -m pip install cibuildwheel + - python3 -m pip install cibuildwheel==2.15.0 run_cibuildwheel_script: - python3 -m cibuildwheel --output-dir wheelhouse wheels_artifacts: diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 2e7db7f1a..ca1fe8ee5 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -13,21 +13,11 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 - name: Install Python - with: - python-version: '3.9' - - - name: Install cibuildwheel - run: | - python -m pip install cibuildwheel - - name: Build wheels - run: | - python -m cibuildwheel --output-dir wheelhouse + uses: pypa/cibuildwheel@v2.15.0 env: - # Skip Python 2.7, 3.5, 3.11, 32 bit Linux, and PyPy - CIBW_SKIP: cp27-* cp35-* *-manylinux_i686 *musllinux* pp* + # Skip Python 3.12, 32 bit Linux, and PyPy + CIBW_SKIP: cp312-* *-manylinux_i686 *musllinux* pp* CIBW_BEFORE_ALL_LINUX: yum install -y tk mesa-libGLU-devel CIBW_BEFORE_BUILD: > pip install cython FXrays low_index sphinx sphinx_rtd_theme && diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 521cccbfd..f297a6633 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -13,21 +13,11 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 - name: Install Python - with: - python-version: '3.9' - - - name: Install cibuildwheel - run: | - python -m pip install cibuildwheel - - name: Build wheels - run: | - python -m cibuildwheel --output-dir wheelhouse + uses: pypa/cibuildwheel@v2.15.0 env: - # Skip Python 2.7, 3.5, 3.11, 32 bit Linux, and PyPy - CIBW_SKIP: cp27-* cp35-* cp36-* cp37-* pp* + # Skip Python 3.12 and PyPy + CIBW_SKIP: cp312-* pp* CIBW_ARCHS_MACOS: x86_64 universal2 CIBW_BEFORE_BUILD: > pip install cython FXrays low_index sphinx sphinx_rtd_theme && diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 114da4430..1a4f2b034 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -8,26 +8,16 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [windows-latest] + os: [windows-2019] steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 - name: Install Python - with: - python-version: '3.9' - - - name: Install cibuildwheel - run: | - python -m pip install cibuildwheel - - name: Build wheels - run: | - python -m cibuildwheel --output-dir wheelhouse + uses: pypa/cibuildwheel@v2.15.0 env: - # Skip Python 2.7, 3.5, 3.11, and PyPy - CIBW_SKIP: cp27-* cp35-* pp* + # Skip Python 3.12, and PyPy + CIBW_SKIP: cp312-* pp* CIBW_BEFORE_BUILD: > pip install cython FXrays low_index sphinx sphinx_rtd_theme && pip install --pre --extra-index-url https://test.pypi.org/simple cypari && From 6c20e8d894646c9b6cced1b2a95e2a49cbcd95de Mon Sep 17 00:00:00 2001 From: Nathan Dunfield Date: Mon, 14 Aug 2023 10:46:16 -0500 Subject: [PATCH 3/5] CI: prevent macos_older_pythons from building 3.12 as well --- .github/workflows/macos.yml | 4 ++-- .github/workflows/macos_older_pythons.yml | 21 +++++---------------- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index f297a6633..500de0354 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -16,8 +16,8 @@ jobs: - name: Build wheels uses: pypa/cibuildwheel@v2.15.0 env: - # Skip Python 3.12 and PyPy - CIBW_SKIP: cp312-* pp* + # Skip Python 3.12 for now + CIBW_BUILD: cp310-* cp311-* CIBW_ARCHS_MACOS: x86_64 universal2 CIBW_BEFORE_BUILD: > pip install cython FXrays low_index sphinx sphinx_rtd_theme && diff --git a/.github/workflows/macos_older_pythons.yml b/.github/workflows/macos_older_pythons.yml index 389f24568..04a376950 100644 --- a/.github/workflows/macos_older_pythons.yml +++ b/.github/workflows/macos_older_pythons.yml @@ -1,4 +1,4 @@ -name: macOS Older Python Wheels +name: macOS Wheels on: [push, pull_request] @@ -13,22 +13,11 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 - name: Install Python - with: - python-version: '3.9' - - - name: Install cibuildwheel - run: | - python -m pip install cibuildwheel - - name: Build wheels - run: | - python -m cibuildwheel --output-dir wheelhouse + uses: pypa/cibuildwheel@v2.15.0 env: - # Skip Python 2.7, 3.5, 3.11, 32 bit Linux, and PyPy - CIBW_SKIP: cp27-* cp35-* cp38-* cp39-* cp310-* cp311-* pp* - CIBW_ARCHS_MACOS: x86_64 + CIBW_BUILD: cp36-* cp37-* cp38-* cp39-* + CIBW_ARCHS_MACOS: x86_64 universal2 CIBW_BEFORE_BUILD: > pip install cython FXrays low_index sphinx sphinx_rtd_theme && pip install --pre --extra-index-url https://test.pypi.org/simple cypari && @@ -45,5 +34,5 @@ jobs: - uses: actions/upload-artifact@v3 with: - name: snappy_macos_older_wheels + name: snappy_macos_wheels path: ./wheelhouse/*.whl From fa4553266f0e78141de9874b88d64ec69c008523 Mon Sep 17 00:00:00 2001 From: Nathan Dunfield Date: Fri, 8 Sep 2023 15:02:25 -0500 Subject: [PATCH 4/5] Windows app: switch over to 64bit for good --- windows_exe/InnoSnapPy_dbg.iss | 1 + windows_exe/InnoSnapPy_py3.iss | 1 + windows_exe/make.py | 12 ++++-------- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/windows_exe/InnoSnapPy_dbg.iss b/windows_exe/InnoSnapPy_dbg.iss index 6e444bbe9..ac1c6a7f5 100644 --- a/windows_exe/InnoSnapPy_dbg.iss +++ b/windows_exe/InnoSnapPy_dbg.iss @@ -19,6 +19,7 @@ OutputDir=. OutputBaseFilename=InstallSnapPy-Dbg Compression=lzma SolidCompression=yes +ArchitecturesInstallIn64BitMode=x64 [Languages] Name: "english"; MessagesFile: "compiler:Default.isl" diff --git a/windows_exe/InnoSnapPy_py3.iss b/windows_exe/InnoSnapPy_py3.iss index 2d50ec548..3b69e001d 100644 --- a/windows_exe/InnoSnapPy_py3.iss +++ b/windows_exe/InnoSnapPy_py3.iss @@ -19,6 +19,7 @@ OutputDir=. OutputBaseFilename=InstallSnapPy-Python3 Compression=lzma SolidCompression=yes +ArchitecturesInstallIn64BitMode=x64 [Languages] Name: "english"; MessagesFile: "compiler:Default.isl" diff --git a/windows_exe/make.py b/windows_exe/make.py index 97a2e84f0..8092387a9 100755 --- a/windows_exe/make.py +++ b/windows_exe/make.py @@ -5,14 +5,10 @@ this_pyinstaller = os.path.abspath( os.path.join(this_python, '..', 'Scripts', 'pyinstaller')) -# We currently build the Windows apps as 32 bit apps only. The reason for -# this is a mysterious unresolved issue with the 64 bit app, namely -# that when installed in C:\Program Files it takes close to one minute -# to start up. While it does start up normally if installed elsewhere, -# we want to resolve this issue before releasing a 64 bit app. - -if platform.architecture()[0] != '32bit' and '--64-bit' not in sys.argv: - print("ERROR: Need to use a 32bit Python to build the apps") +# The Inno Installer config file (*.iss) assumes a 64 bit binary. + +if platform.architecture()[0] != '64bit' and '--32-bit' not in sys.argv: + print("ERROR: Need to use a 64bit Python to build the apps") sys.exit(1) try: From 59d46e903633b3fd4221f003023bf340b666a5e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 10 Sep 2023 18:22:21 +0200 Subject: [PATCH 5/5] cleanup one file (full pep8, other details) (#114) --- python/ptolemy/polynomial.py | 105 ++++++++++++++++------------------- 1 file changed, 49 insertions(+), 56 deletions(-) diff --git a/python/ptolemy/polynomial.py b/python/ptolemy/polynomial.py index 427c81abb..e175f3530 100644 --- a/python/ptolemy/polynomial.py +++ b/python/ptolemy/polynomial.py @@ -1,10 +1,6 @@ import re import operator from fractions import Fraction -import sys - -long = int -unicode = str ####################################################### # Public Definitions of Monomial and Polynomial class @@ -21,7 +17,7 @@ class Monomial(): @classmethod def from_variable_name(cls, var): """Construct a monomial with a single variable given as a string.""" - assert isinstance(var, str) or isinstance(var, unicode) + assert isinstance(var, str) return Monomial(1, ((var, 1),)) # Constructs a constant monomial @@ -47,7 +43,7 @@ def __init__(self, coefficient, vars): else: assert isinstance(vars, tuple) for var, expo in vars: - assert isinstance(var, str) or isinstance(var, unicode) + assert isinstance(var, str) assert isinstance(expo, int) assert expo > 0 self._vars = vars @@ -124,7 +120,7 @@ def __mul__(self, other): # Compute the variables var_dict = _combine_dicts( - [dict(self._vars),dict(other._vars)], + [dict(self._vars), dict(other._vars)], operator.add) return Monomial(coefficient, var_dict) @@ -138,9 +134,9 @@ def __pow__(self, other): return Monomial.constant_monomial(1) if other == 1: return self - if other % 2 == 1: - return self * (self ** (other-1)) - return (self * self) ** (other//2) + if other % 2: + return self * (self ** (other - 1)) + return (self * self) ** (other // 2) def __neg__(self): """Negate this monomial.""" @@ -166,7 +162,7 @@ def convert_coefficient(self, conversion_function): def split_variable(self, variable): """Split the specified variable from the others.""" - remaining_terms = { } + remaining_terms = {} exponent = 0 for var, expo in self._vars: if var == variable: @@ -258,12 +254,12 @@ class Polynomial(): @classmethod def constant_polynomial(cls, constant): """Construct a constant polynomial.""" - return Polynomial( (Monomial.constant_monomial(constant),)) + return Polynomial((Monomial.constant_monomial(constant),)) @classmethod def from_variable_name(cls, var): """Construct a polynomial consisting of a single variable.""" - return Polynomial( (Monomial.from_variable_name(var),)) + return Polynomial((Monomial.from_variable_name(var),)) # constructor takes a tuple of polynomials which are combined @@ -279,7 +275,7 @@ def __init__(self, monomials=()): # and value being the coefficient list_of_vars_coeff_dicts = [ - { monomial.get_vars() : monomial.get_coefficient() } + {monomial.get_vars(): monomial.get_coefficient()} for monomial in monomials] # combine the dictionaries using sum @@ -327,9 +323,9 @@ def __pow__(self, other): return Polynomial((Monomial.constant_monomial(1),)) if other == 1: return self - if other % 2 == 1: - return self * (self ** (other-1)) - return (self * self) ** (other//2) + if other % 2: + return self * (self ** (other - 1)) + return (self * self) ** (other // 2) def __mul__(self, other): monomials = [] @@ -352,7 +348,7 @@ def __mod__(self, other): other = other.convert_coefficients(Fraction) other = other * Polynomial.constant_polynomial( - Fraction(1,1) / other.leading_coefficient()) + Fraction(1, 1) / other.leading_coefficient()) variable = other.variables()[0] assert ((not other.variables()) @@ -392,8 +388,8 @@ def convert_coefficients(self, conversion_function): """Convert all coefficients using conversion_function.""" return Polynomial(tuple( - [monomial.convert_coefficient(conversion_function) - for monomial in self._monomials])) + [monomial.convert_coefficient(conversion_function) + for monomial in self._monomials])) def substitute(self, d): """ @@ -417,11 +413,11 @@ def substitute_monomial(monomial): for var, expo in vars: if var not in d: - new_vars.append((var,expo)) + new_vars.append((var, expo)) poly = Polynomial(( - Monomial(monomial.get_coefficient(), - tuple(new_vars)),)) + Monomial(monomial.get_coefficient(), + tuple(new_vars)),)) for var, expo in vars: if var in d: @@ -430,7 +426,7 @@ def substitute_monomial(monomial): return poly return sum([substitute_monomial(monomial) - for monomial in self._monomials], Polynomial(())) + for monomial in self._monomials], Polynomial(())) def variables(self): """Return a list of all variables in the polynomial.""" @@ -478,11 +474,11 @@ def is_monic(self): """Assert univariance; return True iff this polynomial is monic.""" return self.leading_coefficient() == 1 - def get_coefficients(self, conversion_function=lambda x:x): + def get_coefficients(self, conversion_function=lambda x: x): """Assert univariance; return the coefficients in degree order.""" assert self.is_univariate() degree = self.degree() - list_of_coefficients = (degree + 1) * [ conversion_function(0) ] + list_of_coefficients = (degree + 1) * [conversion_function(0)] for monomial in self._monomials: list_of_coefficients[degree - monomial.degree()] = ( conversion_function(monomial.get_coefficient())) @@ -533,7 +529,7 @@ def get_monomials(self): def factor_out_variables(self): - if self._monomials == (): + if not self._monomials: return self def intersect(lists): @@ -543,22 +539,21 @@ def intersect(lists): return s non_trivial_variables = intersect( - [ monomial.variables() for monomial in self._monomials]) + [monomial.variables() for monomial in self._monomials]) - lowest_powers = dict([ (var,1000000) for var in non_trivial_variables ]) + lowest_powers = {var: 1000000 for var in non_trivial_variables} - def safe_dict(d,var): + def safe_dict(d, var): if var in d: return d[var] - else: - return 0 + return 0 for monomial in self._monomials: for var, expo in monomial.get_vars(): - lowest_powers[var] = min(safe_dict(lowest_powers,var), expo) + lowest_powers[var] = min(safe_dict(lowest_powers, var), expo) - return Polynomial(tuple([ monomial.reduce_exponents(lowest_powers) - for monomial in self._monomials])) + return Polynomial(tuple([monomial.reduce_exponents(lowest_powers) + for monomial in self._monomials])) ############################################################### # Default functions for parsing and printing the coefficients @@ -568,7 +563,7 @@ def safe_dict(d,var): def parse_int_coefficient(s): - coeff, rest = re.match('([0-9]*)(.*)',s).groups() + coeff, rest = re.match('([0-9]*)(.*)', s).groups() if coeff: coeff = int(coeff) else: @@ -577,7 +572,7 @@ def parse_int_coefficient(s): def parse_int_or_fraction(s): - m = re.match('([0-9]+/[0-9]+)(.*)',s) + m = re.match('([0-9]+/[0-9]+)(.*)', s) if m: frac, rest = m.groups() return Fraction(frac), rest @@ -623,9 +618,9 @@ def _storage_type_policy(type_a, type_b): assert isinstance(type_a, type) assert isinstance(type_b, type) - if type_a in [int, long]: + if type_a in [int]: return type_b - if type_b in [int, long]: + if type_b in [int]: return type_a if not type_a == type_b: @@ -642,9 +637,9 @@ def _operator_type_policy(obj_a, obj_b, op=operator.add): if type(obj_a) == type(obj_b): return op(obj_a, obj_b) - if type(obj_a) in [int, long]: + if type(obj_a) in [int]: return op(type(obj_b)(obj_a), obj_b) - if type(obj_b) in [int, long]: + if type(obj_b) in [int]: return op(type(obj_a)(obj_b), obj_a) raise Exception @@ -660,23 +655,21 @@ def _operator_type_policy(obj_a, obj_b, op=operator.add): _operators = { - '+' : operator.add, - '-' : operator.sub, - '*' : operator.mul, - '^' : operator.pow - } + '+': operator.add, + '-': operator.sub, + '*': operator.mul, + '^': operator.pow} _operator_precedence = { - None : 0, - '+' : 1, - '-' : 1, - '*' : 2, - '^' : 3 - } + None: 0, + '+': 1, + '-': 1, + '*': 2, + '^': 3} def _apply_operator(op, l, r): - return _operators[op](l,r) + return _operators[op](l, r) # Helper functions for parsing @@ -690,7 +683,7 @@ def _coefficient_is_non_trivial(c): def _parse_variable(s): - r = re.match(r'([_A-Za-z][_A-Za-z0-9]*)(.*)$',s) + r = re.match(r'([_A-Za-z][_A-Za-z0-9]*)(.*)$', s) if r: return r.groups() else: @@ -709,7 +702,7 @@ def _parse_polynomial_from_string(s, parse_coefficient_function): # Has there been an operand since the opening parenthesis # e.g. parse things like "(+ x)" - no_operand_since_opening_parenthesis = [ True ] + no_operand_since_opening_parenthesis = [True] def debug_print(s): print("=" * 75) @@ -730,7 +723,7 @@ def eval_preceding_operators_on_stack(operator=None): # or if the top operator is not preceding if (_operator_precedence[top_operator] < - _operator_precedence[operator]): + _operator_precedence[operator]): return top_operator = operator_stack.pop()