From ea74cb8d6e725a59eeb3fe02c72a937969ce7ccf Mon Sep 17 00:00:00 2001 From: Alessandro Molina Date: Tue, 21 Apr 2026 10:03:07 +0000 Subject: [PATCH 1/3] Update codebase --- devtools/gearbox/quickstart/command.py | 4 +--- .../tests/functional/test_authentication.py_tmpl | 2 -- .../template/+package+/tests/functional/test_root.py_tmpl | 2 +- .../template/+package+/tests/models/test_auth.py_tmpl | 2 -- .../template/+package+/websetup/bootstrap.py_tmpl | 2 -- .../quickstart/template/+package+/websetup/schema.py_tmpl | 4 +--- .../gearbox/quickstart/template/migration/env.py_tmpl | 1 - devtools/gearbox/sqlamigrate.py | 7 +------ devtools/gearbox/tgext/command.py | 2 -- devtools/gearbox/tgext/template/pyproject.toml_tmpl | 4 ++-- devtools/gearbox/tgext/template/tgext/__init__.py | 7 ------- devtools/gearbox/tgshell.py | 8 +++----- devtools/tests/test_quickstart.py | 1 - 13 files changed, 9 insertions(+), 37 deletions(-) delete mode 100644 devtools/gearbox/tgext/template/tgext/__init__.py diff --git a/devtools/gearbox/quickstart/command.py b/devtools/gearbox/quickstart/command.py index 794467ec..9bfd5328 100644 --- a/devtools/gearbox/quickstart/command.py +++ b/devtools/gearbox/quickstart/command.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import re import os import shutil @@ -244,4 +242,4 @@ def safe_name(name: str) -> str: from setuptools.pkg_resources.safe_name """ - return re.sub('[^A-Za-z0-9.]+', '-', name) \ No newline at end of file + return re.sub('[^A-Za-z0-9.]+', '-', name) diff --git a/devtools/gearbox/quickstart/template/+package+/tests/functional/test_authentication.py_tmpl b/devtools/gearbox/quickstart/template/+package+/tests/functional/test_authentication.py_tmpl index e5533ac0..d853bfa9 100644 --- a/devtools/gearbox/quickstart/template/+package+/tests/functional/test_authentication.py_tmpl +++ b/devtools/gearbox/quickstart/template/+package+/tests/functional/test_authentication.py_tmpl @@ -7,8 +7,6 @@ As {{project}} grows and the authentication method changes, only these tests should be updated. """ -from __future__ import unicode_literals - from {{package}}.tests import TestController diff --git a/devtools/gearbox/quickstart/template/+package+/tests/functional/test_root.py_tmpl b/devtools/gearbox/quickstart/template/+package+/tests/functional/test_root.py_tmpl index 7192c7ed..9de9ab00 100644 --- a/devtools/gearbox/quickstart/template/+package+/tests/functional/test_root.py_tmpl +++ b/devtools/gearbox/quickstart/template/+package+/tests/functional/test_root.py_tmpl @@ -25,7 +25,7 @@ class TestRootController(TestController): assert msg in response # You can also access a BeautifulSoup'ed response in your tests - # (First run $ easy_install BeautifulSoup + # (First run `pip install beautifulsoup4` # and then uncomment the next two lines) # links = response.html.findAll('a') diff --git a/devtools/gearbox/quickstart/template/+package+/tests/models/test_auth.py_tmpl b/devtools/gearbox/quickstart/template/+package+/tests/models/test_auth.py_tmpl index 61069678..162739b2 100644 --- a/devtools/gearbox/quickstart/template/+package+/tests/models/test_auth.py_tmpl +++ b/devtools/gearbox/quickstart/template/+package+/tests/models/test_auth.py_tmpl @@ -1,7 +1,5 @@ # -*- coding: utf-8 -*- """Test suite for the TG app's models""" -from __future__ import unicode_literals - from {{package}} import model from {{package}}.tests.models import ModelTest diff --git a/devtools/gearbox/quickstart/template/+package+/websetup/bootstrap.py_tmpl b/devtools/gearbox/quickstart/template/+package+/websetup/bootstrap.py_tmpl index 37d86ecd..4a2c4b6d 100644 --- a/devtools/gearbox/quickstart/template/+package+/websetup/bootstrap.py_tmpl +++ b/devtools/gearbox/quickstart/template/+package+/websetup/bootstrap.py_tmpl @@ -1,7 +1,5 @@ # -*- coding: utf-8 -*- """Setup the {{project}} application""" -from __future__ import print_function, unicode_literals - {{if sqlalchemy}} import transaction {{endif}} diff --git a/devtools/gearbox/quickstart/template/+package+/websetup/schema.py_tmpl b/devtools/gearbox/quickstart/template/+package+/websetup/schema.py_tmpl index d7e5e192..1a9a8554 100644 --- a/devtools/gearbox/quickstart/template/+package+/websetup/schema.py_tmpl +++ b/devtools/gearbox/quickstart/template/+package+/websetup/schema.py_tmpl @@ -1,7 +1,5 @@ # -*- coding: utf-8 -*- """Setup the {{project}} application""" -from __future__ import print_function - from tg import config {{if sqlalchemy}} import transaction @@ -32,4 +30,4 @@ def setup_schema(command, conf, vars): alembic_cfg.set_main_option("sqlalchemy.url", config['sqlalchemy.url']) import alembic.command alembic.command.stamp(alembic_cfg, "head") - {{endif}} \ No newline at end of file + {{endif}} diff --git a/devtools/gearbox/quickstart/template/migration/env.py_tmpl b/devtools/gearbox/quickstart/template/migration/env.py_tmpl index 06d1ac93..5df5faa6 100644 --- a/devtools/gearbox/quickstart/template/migration/env.py_tmpl +++ b/devtools/gearbox/quickstart/template/migration/env.py_tmpl @@ -1,4 +1,3 @@ -from __future__ import with_statement from alembic import context from sqlalchemy import engine_from_config, pool diff --git a/devtools/gearbox/sqlamigrate.py b/devtools/gearbox/sqlamigrate.py index fca6f369..202205e0 100644 --- a/devtools/gearbox/sqlamigrate.py +++ b/devtools/gearbox/sqlamigrate.py @@ -37,14 +37,9 @@ check http://code.google.com/p/sqlalchemy-migrate/wiki/MigrateVersioning for detail. """ -from __future__ import print_function +from configparser import ConfigParser from gearbox.command import Command -try: - from configparser import ConfigParser -except ImportError: - from ConfigParser import ConfigParser - import sys, os class MigrateCommand(Command): diff --git a/devtools/gearbox/tgext/command.py b/devtools/gearbox/tgext/command.py index b93451ca..3b207516 100644 --- a/devtools/gearbox/tgext/command.py +++ b/devtools/gearbox/tgext/command.py @@ -1,5 +1,3 @@ -from __future__ import print_function - from gearbox.command import TemplateCommand import re, getpass diff --git a/devtools/gearbox/tgext/template/pyproject.toml_tmpl b/devtools/gearbox/tgext/template/pyproject.toml_tmpl index e7aeb986..240865c1 100644 --- a/devtools/gearbox/tgext/template/pyproject.toml_tmpl +++ b/devtools/gearbox/tgext/template/pyproject.toml_tmpl @@ -7,8 +7,9 @@ name = {{repr(package)}} version = "{{version}}" description = "{{description or ''}}" readme = { file = "README.rst", content-type = "text/x-rst" } +requires-python = ">=3.8" classifiers = [] # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers -keywords = {{repr(keywords or '')}} +keywords = [{{repr(keywords or '')}}] authors = [ { name = {{repr(author or '')}}, email = {{repr(author_email or '')}} } ] @@ -24,4 +25,3 @@ exclude = ["ez_setup", "examples", "tests"] [tool.setuptools] include-package-data = true zip-safe = false -namespace_packages = ["tgext"] diff --git a/devtools/gearbox/tgext/template/tgext/__init__.py b/devtools/gearbox/tgext/template/tgext/__init__.py deleted file mode 100644 index 5761d9e1..00000000 --- a/devtools/gearbox/tgext/template/tgext/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages -try: - __import__('pkg_resources').declare_namespace(__name__) -except ImportError: - from pkgutil import extend_path - __path__ = extend_path(__path__, __name__) - diff --git a/devtools/gearbox/tgshell.py b/devtools/gearbox/tgshell.py index a26e159b..7c9b539b 100644 --- a/devtools/gearbox/tgshell.py +++ b/devtools/gearbox/tgshell.py @@ -1,5 +1,3 @@ -from __future__ import print_function - import os, sys import tg @@ -71,9 +69,9 @@ def take_action(self, opts): if self._can_import(helpers_module): locs['h'] = sys.modules[helpers_module] - exec ('import tg') in locs - exec ('from tg import app_globals, config, request, response, ' - 'session, tmpl_context, url') in locs + exec('import tg', locs) + exec('from tg import app_globals, config, request, response, ' + 'session, tmpl_context, url', locs) locs.pop('__builtins__', None) # Import all objects from the base module diff --git a/devtools/tests/test_quickstart.py b/devtools/tests/test_quickstart.py index 0f69a3bd..ac09d243 100644 --- a/devtools/tests/test_quickstart.py +++ b/devtools/tests/test_quickstart.py @@ -15,7 +15,6 @@ PY_VERSION = sys.version_info[:2] -PY2 = sys.version_info[0] == 2 PROJECT_NAME = 'TGTest-%02d' ENV_NAME = 'TESTENV' CLEANUP = True From 5e7bf3831b4a663cfac50c7e2ddf58dcd4e3064b Mon Sep 17 00:00:00 2001 From: Alessandro Molina Date: Tue, 21 Apr 2026 20:40:42 +0000 Subject: [PATCH 2/3] Tweaks --- .github/workflows/run-tests.yml | 11 +++++++++-- pyproject.toml | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index c07d20d7..138f4524 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -1,12 +1,19 @@ name: run-tests -on: [push, pull_request, workflow_dispatch] +on: + push: + branches: + - main + - master + - development + pull_request: + workflow_dispatch: jobs: build: name: Run tests strategy: matrix: os: [ubuntu-latest] - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 diff --git a/pyproject.toml b/pyproject.toml index 340a354e..96570f1b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,6 +6,7 @@ build-backend = "setuptools.build_meta" name = "tg.devtools" version = "2.5.1dev1" description = "TurboGears 2 DevTools is a command-line toolkit that streamlines TurboGears2 development." +requires-python = ">=3.10" readme = { file = "README.rst", content-type = "text/x-rst" } keywords = ["turbogears", "devtools", "cli", "scaffold", "gearbox"] classifiers = [] From 89c532ff0110b165c57c456bc61a56821acaccec Mon Sep 17 00:00:00 2001 From: Alessandro Molina Date: Sun, 17 May 2026 20:51:30 +0000 Subject: [PATCH 3/3] use f-strings --- .../template/+package+/controllers/root.py_tmpl | 2 +- .../quickstart/template/+package+/lib/helpers.py_tmpl | 2 +- .../quickstart/template/+package+/model/auth.py_tmpl | 10 +++------- .../template/+package+/tests/__init__.py_tmpl | 2 +- .../tests/functional/test_authentication.py_tmpl | 6 +++--- devtools/gearbox/quickstart/template/setup.py_tmpl | 4 ---- 6 files changed, 9 insertions(+), 17 deletions(-) delete mode 100755 devtools/gearbox/quickstart/template/setup.py_tmpl diff --git a/devtools/gearbox/quickstart/template/+package+/controllers/root.py_tmpl b/devtools/gearbox/quickstart/template/+package+/controllers/root.py_tmpl index b7b42ca3..758d5ba8 100644 --- a/devtools/gearbox/quickstart/template/+package+/controllers/root.py_tmpl +++ b/devtools/gearbox/quickstart/template/+package+/controllers/root.py_tmpl @@ -115,7 +115,7 @@ class RootController(BaseController): redirect('/login', params=dict(came_from=came_from, __logins=login_counter)) userid = request.identity['repoze.who.userid'] - flash(_('Welcome back, %s!') % userid) + flash(_('Welcome back, {}!').format(userid)) # Do not use tg.redirect with tg.url as it will add the mountpoint # of the application twice. diff --git a/devtools/gearbox/quickstart/template/+package+/lib/helpers.py_tmpl b/devtools/gearbox/quickstart/template/+package+/lib/helpers.py_tmpl index f9f6bf7d..d3526873 100644 --- a/devtools/gearbox/quickstart/template/+package+/lib/helpers.py_tmpl +++ b/devtools/gearbox/quickstart/template/+package+/lib/helpers.py_tmpl @@ -13,7 +13,7 @@ def current_year(): def icon(icon_name): - return Markup('' % icon_name) + return Markup(f'') # Import commonly used helpers from WebHelpers2 and TG diff --git a/devtools/gearbox/quickstart/template/+package+/model/auth.py_tmpl b/devtools/gearbox/quickstart/template/+package+/model/auth.py_tmpl index e2f111f4..ac90da70 100644 --- a/devtools/gearbox/quickstart/template/+package+/model/auth.py_tmpl +++ b/devtools/gearbox/quickstart/template/+package+/model/auth.py_tmpl @@ -72,7 +72,7 @@ class Group(DeclarativeBase): users = relationship('User', secondary=user_group_table, backref='groups') def __repr__(self): - return '' % repr(self.group_name) + return f'' def __unicode__(self): return self.group_name @@ -96,11 +96,7 @@ class User(DeclarativeBase): created = Column(DateTime, default=datetime.now) def __repr__(self): - return '' % ( - repr(self.user_name), - repr(self.email_address), - repr(self.display_name) - ) + return f'' def __unicode__(self): return self.display_name or self.user_name @@ -185,7 +181,7 @@ class Permission(DeclarativeBase): backref='permissions') def __repr__(self): - return '' % repr(self.permission_name) + return f'' def __unicode__(self): return self.permission_name diff --git a/devtools/gearbox/quickstart/template/+package+/tests/__init__.py_tmpl b/devtools/gearbox/quickstart/template/+package+/tests/__init__.py_tmpl index ed348547..b0d85e14 100644 --- a/devtools/gearbox/quickstart/template/+package+/tests/__init__.py_tmpl +++ b/devtools/gearbox/quickstart/template/+package+/tests/__init__.py_tmpl @@ -17,7 +17,7 @@ application_name = 'main_without_authn' def load_app(name=application_name): """Load the test application.""" - return TestApp(loadapp('config:test.ini#%s' % name, relative_to=getcwd())) + return TestApp(loadapp(f'config:test.ini#{name}', relative_to=getcwd())) def setup_app(): diff --git a/devtools/gearbox/quickstart/template/+package+/tests/functional/test_authentication.py_tmpl b/devtools/gearbox/quickstart/template/+package+/tests/functional/test_authentication.py_tmpl index d853bfa9..26e6b8b5 100644 --- a/devtools/gearbox/quickstart/template/+package+/tests/functional/test_authentication.py_tmpl +++ b/devtools/gearbox/quickstart/template/+package+/tests/functional/test_authentication.py_tmpl @@ -34,7 +34,7 @@ class TestAuthentication(TestController): home_page = post_login.follow(status=302) assert ( 'authtkt' in home_page.request.cookies - ), 'Session cookie was not defined: %s' % home_page.request.cookies + ), f'Session cookie was not defined: {home_page.request.cookies}' assert home_page.location, 'http://localhost/' def test_logout(self): @@ -45,7 +45,7 @@ class TestAuthentication(TestController): resp = resp.follow(status=302) assert ( 'authtkt' in resp.request.cookies - ), 'Session cookie was not defined: %s' % resp.request.cookies + ), f'Session cookie was not defined: {resp.request.cookies}' # Logging out: resp = self.app.get('/logout_handler', status=302) assert resp.location.startswith('http://localhost/post_logout') @@ -54,7 +54,7 @@ class TestAuthentication(TestController): authtkt = home_page.request.cookies.get('authtkt') assert ( not authtkt or authtkt == 'INVALID' - ), 'Session cookie was not deleted: %s' % home_page.request.cookies + ), f'Session cookie was not deleted: {home_page.request.cookies}' assert home_page.location == 'http://localhost/' def test_failed_login_keeps_username(self): diff --git a/devtools/gearbox/quickstart/template/setup.py_tmpl b/devtools/gearbox/quickstart/template/setup.py_tmpl deleted file mode 100755 index 57c026bf..00000000 --- a/devtools/gearbox/quickstart/template/setup.py_tmpl +++ /dev/null @@ -1,4 +0,0 @@ -from setuptools import setup - -if __name__ == "__main__": - setup() \ No newline at end of file