diff --git a/.github/workflows/bugwarrior.yml b/.github/workflows/bugwarrior.yml index c3219f6c..b0abca97 100644 --- a/.github/workflows/bugwarrior.yml +++ b/.github/workflows/bugwarrior.yml @@ -10,7 +10,7 @@ jobs: timeout-minutes: 5 strategy: matrix: - python-version: [3.7, 3.8, 3.9, "3.10", 3.11] + python-version: [3.8, 3.9, "3.10", 3.11] jira-version: [1.0.10, 2.0.0] steps: - name: Checkout code @@ -50,7 +50,7 @@ jobs: timeout-minutes: 60 strategy: matrix: - python-version: [3.7, 3.8, 3.9, "3.10", 3.11] + python-version: [3.8, 3.9, "3.10", 3.11] jira-version: [1.0.10, 2.0.0] architecture: [aarch64, ppc64le] diff --git a/bugwarrior/config/schema.py b/bugwarrior/config/schema.py index 8b2d1ffa..04a5f931 100644 --- a/bugwarrior/config/schema.py +++ b/bugwarrior/config/schema.py @@ -8,7 +8,6 @@ import pydantic.v1 import pydantic.v1.error_wrappers import taskw -import typing_extensions from bugwarrior.collect import get_service @@ -139,7 +138,7 @@ def compute_data(cls, values): static_tags: ConfigList = ConfigList([]) static_fields: ConfigList = ConfigList(['priority']) - log_level: typing_extensions.Literal[ + log_level: typing.Literal[ ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL', 'DISABLED') ] = 'INFO' log_file: typing.Optional[LoggingPath] = None @@ -152,7 +151,7 @@ class Hooks(pydantic.v1.BaseModel): class Notifications(pydantic.v1.BaseModel): notifications: bool = False # Although upstream supports it, pydantic has problems with Literal[None]. - backend: typing.Optional[typing_extensions.Literal[ + backend: typing.Optional[typing.Literal[ ('gobject', 'growlnotify', 'applescript')]] = None finished_querying_sticky: bool = True task_crud_sticky: bool = True @@ -306,7 +305,7 @@ class ServiceConfig(_ServiceConfig): # type: ignore # (dynamic base class) # Optional fields shared by all services. only_if_assigned: str = '' also_unassigned: bool = False - default_priority: typing_extensions.Literal['', 'L', 'M', 'H'] = 'M' + default_priority: typing.Literal['', 'L', 'M', 'H'] = 'M' add_tags: ConfigList = ConfigList([]) description_template: typing.Optional[str] = None diff --git a/bugwarrior/docs/other-services/tutorial.rst b/bugwarrior/docs/other-services/tutorial.rst index 5afa041b..91c40862 100644 --- a/bugwarrior/docs/other-services/tutorial.rst +++ b/bugwarrior/docs/other-services/tutorial.rst @@ -49,9 +49,9 @@ Fire up your favorite editor and import the base classes and whatever library yo import logging import pathlib + import typing import requests - import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue, Client @@ -69,7 +69,7 @@ Now define an initial configuration schema as follows. Don't worry, we're about .. code:: python class GitbugConfig(config.ServiceConfig): - service: typing_extensions.Literal['gitbug'] + service: typing.Literal['gitbug'] path: pathlib.Path diff --git a/bugwarrior/services/__init__.py b/bugwarrior/services/__init__.py index 23962f8a..b07c7a91 100644 --- a/bugwarrior/services/__init__.py +++ b/bugwarrior/services/__init__.py @@ -13,7 +13,6 @@ from jinja2 import Template import pytz import requests -import typing_extensions from bugwarrior.config import schema, secrets @@ -154,7 +153,7 @@ def get_tags_from_labels(self, return tags - def get_priority(self) -> typing_extensions.Literal['', 'L', 'M', 'H']: + def get_priority(self) -> typing.Literal['', 'L', 'M', 'H']: """ Return the priority of this issue, falling back to ``default_priority`` configuration. """ return self.PRIORITY_MAP.get( diff --git a/bugwarrior/services/activecollab.py b/bugwarrior/services/activecollab.py index abe824a9..9279f828 100644 --- a/bugwarrior/services/activecollab.py +++ b/bugwarrior/services/activecollab.py @@ -1,8 +1,8 @@ import re +import typing import pypandoc from pyac.library import activeCollab -import typing_extensions from bugwarrior.services import Service, Issue from bugwarrior import config @@ -11,7 +11,7 @@ class ActiveCollabConfig(config.ServiceConfig): - service: typing_extensions.Literal['activecollab'] + service: typing.Literal['activecollab'] url: config.StrippedTrailingSlashUrl key: str user_id: int diff --git a/bugwarrior/services/activecollab2.py b/bugwarrior/services/activecollab2.py index 44150010..a8c5e197 100644 --- a/bugwarrior/services/activecollab2.py +++ b/bugwarrior/services/activecollab2.py @@ -1,8 +1,8 @@ import itertools import time +import typing import requests -import typing_extensions from bugwarrior.services import Service, Issue, Client from bugwarrior import config @@ -31,7 +31,7 @@ def validate(cls, projects_raw): class ActiveCollab2Config(config.ServiceConfig): - service: typing_extensions.Literal['activecollab2'] + service: typing.Literal['activecollab2'] url: config.StrippedTrailingSlashUrl key: str user_id: int diff --git a/bugwarrior/services/azuredevops.py b/bugwarrior/services/azuredevops.py index ecdcdd76..a0ee3095 100644 --- a/bugwarrior/services/azuredevops.py +++ b/bugwarrior/services/azuredevops.py @@ -2,10 +2,10 @@ import logging import re import sys +import typing from urllib.parse import quote import requests -import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue, Client @@ -25,7 +25,7 @@ def validate(cls, value): class AzureDevopsConfig(config.ServiceConfig): - service: typing_extensions.Literal['azuredevops'] + service: typing.Literal['azuredevops'] PAT: str project: EscapedStr organization: EscapedStr diff --git a/bugwarrior/services/bitbucket.py b/bugwarrior/services/bitbucket.py index 6ca5efa1..d82b8ec7 100644 --- a/bugwarrior/services/bitbucket.py +++ b/bugwarrior/services/bitbucket.py @@ -3,7 +3,6 @@ import pydantic.v1 import requests -import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue, Client @@ -13,9 +12,9 @@ class BitbucketConfig(config.ServiceConfig): _DEPRECATE_FILTER_MERGE_REQUESTS = True - filter_merge_requests: typing.Union[bool, typing_extensions.Literal['Undefined']] = 'Undefined' + filter_merge_requests: typing.Union[bool, typing.Literal['Undefined']] = 'Undefined' - service: typing_extensions.Literal['bitbucket'] + service: typing.Literal['bitbucket'] username: str @@ -27,7 +26,7 @@ class BitbucketConfig(config.ServiceConfig): include_repos: config.ConfigList = config.ConfigList([]) exclude_repos: config.ConfigList = config.ConfigList([]) - include_merge_requests: typing.Union[bool, typing_extensions.Literal['Undefined']] = 'Undefined' + include_merge_requests: typing.Union[bool, typing.Literal['Undefined']] = 'Undefined' project_owner_prefix: bool = False @pydantic.v1.root_validator diff --git a/bugwarrior/services/bts.py b/bugwarrior/services/bts.py index e41208ad..4b92d34a 100644 --- a/bugwarrior/services/bts.py +++ b/bugwarrior/services/bts.py @@ -1,8 +1,8 @@ import sys +import typing import pydantic.v1 import requests -import typing_extensions from bugwarrior import config from bugwarrior.services import Issue, Service, Client @@ -22,7 +22,7 @@ class BTSConfig(config.ServiceConfig): - service: typing_extensions.Literal['bts'] + service: typing.Literal['bts'] email: pydantic.v1.EmailStr = pydantic.v1.EmailStr('') packages: config.ConfigList = config.ConfigList([]) diff --git a/bugwarrior/services/bz.py b/bugwarrior/services/bz.py index c24df161..d8c81afc 100644 --- a/bugwarrior/services/bz.py +++ b/bugwarrior/services/bz.py @@ -8,7 +8,6 @@ import bugzilla import pydantic.v1 import pytz -import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue @@ -34,7 +33,7 @@ def validate(cls, value, field, config): class BugzillaConfig(config.ServiceConfig): - service: typing_extensions.Literal['bugzilla'] + service: typing.Literal['bugzilla'] username: str base_uri: OptionalSchemeUrl diff --git a/bugwarrior/services/deck.py b/bugwarrior/services/deck.py index a3764c32..003a1669 100644 --- a/bugwarrior/services/deck.py +++ b/bugwarrior/services/deck.py @@ -1,8 +1,8 @@ import datetime import logging +import typing import requests -import typing_extensions from dateutil.tz import tzutc from bugwarrior import config @@ -12,7 +12,7 @@ class NextcloudDeckConfig(config.ServiceConfig): - service: typing_extensions.Literal['deck'] + service: typing.Literal['deck'] base_uri: config.StrippedTrailingSlashUrl username: str diff --git a/bugwarrior/services/gerrit.py b/bugwarrior/services/gerrit.py index fd133c06..9419b1ed 100644 --- a/bugwarrior/services/gerrit.py +++ b/bugwarrior/services/gerrit.py @@ -2,14 +2,13 @@ import typing import requests -import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue, Client class GerritConfig(config.ServiceConfig): - service: typing_extensions.Literal['gerrit'] + service: typing.Literal['gerrit'] base_uri: config.StrippedTrailingSlashUrl username: str password: str diff --git a/bugwarrior/services/gitbug.py b/bugwarrior/services/gitbug.py index 98efbcf1..d90f4b82 100644 --- a/bugwarrior/services/gitbug.py +++ b/bugwarrior/services/gitbug.py @@ -3,9 +3,9 @@ import signal import subprocess import sys +import typing import requests -import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue, Client @@ -14,7 +14,7 @@ class GitBugConfig(config.ServiceConfig): - service: typing_extensions.Literal['gitbug'] + service: typing.Literal['gitbug'] path: config.ExpandedPath diff --git a/bugwarrior/services/github.py b/bugwarrior/services/github.py index 4b1475ce..b5e24d8f 100644 --- a/bugwarrior/services/github.py +++ b/bugwarrior/services/github.py @@ -1,10 +1,10 @@ import re import sys +import typing import urllib.parse import pydantic.v1 import requests -import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue, Client @@ -17,7 +17,7 @@ class GithubConfig(config.ServiceConfig): password: str = 'Deprecated' # strictly required - service: typing_extensions.Literal['github'] + service: typing.Literal['github'] login: str token: str diff --git a/bugwarrior/services/gitlab.py b/bugwarrior/services/gitlab.py index 25f63326..7ee8ae77 100644 --- a/bugwarrior/services/gitlab.py +++ b/bugwarrior/services/gitlab.py @@ -4,7 +4,6 @@ import pydantic.v1 import sys -import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue, Client @@ -12,14 +11,14 @@ import logging log = logging.getLogger(__name__) -DefaultPriority = typing_extensions.Literal['', 'L', 'M', 'H', 'unassigned'] +DefaultPriority = typing.Literal['', 'L', 'M', 'H', 'unassigned'] class GitlabConfig(config.ServiceConfig): _DEPRECATE_FILTER_MERGE_REQUESTS = True - filter_merge_requests: typing.Union[bool, typing_extensions.Literal['Undefined']] = 'Undefined' + filter_merge_requests: typing.Union[bool, typing.Literal['Undefined']] = 'Undefined' - service: typing_extensions.Literal['gitlab'] + service: typing.Literal['gitlab'] login: str token: str host: config.NoSchemeUrl @@ -32,7 +31,7 @@ class GitlabConfig(config.ServiceConfig): owned: typing.Optional[bool] = None import_labels_as_tags: bool = False label_template: str = '{{label}}' - include_merge_requests: typing.Union[bool, typing_extensions.Literal['Undefined']] = 'Undefined' + include_merge_requests: typing.Union[bool, typing.Literal['Undefined']] = 'Undefined' include_issues: bool = True include_todos: bool = False include_all_todos: bool = True diff --git a/bugwarrior/services/gmail.py b/bugwarrior/services/gmail.py index 5ee27150..235b102e 100644 --- a/bugwarrior/services/gmail.py +++ b/bugwarrior/services/gmail.py @@ -5,11 +5,11 @@ import pickle import re import time +import typing import googleapiclient.discovery from google.auth.transport.requests import Request from google_auth_oauthlib.flow import InstalledAppFlow -import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue @@ -18,7 +18,7 @@ class GmailConfig(config.ServiceConfig): - service: typing_extensions.Literal['gmail'] + service: typing.Literal['gmail'] client_secret_path: config.ExpandedPath = config.ExpandedPath( '~/.gmail_client_secret.json') diff --git a/bugwarrior/services/jira.py b/bugwarrior/services/jira.py index 8019b57e..2cd0e0e6 100644 --- a/bugwarrior/services/jira.py +++ b/bugwarrior/services/jira.py @@ -5,7 +5,6 @@ from functools import reduce import pydantic.v1 -import typing_extensions from dateutil.tz.tz import tzutc from jira.client import JIRA as BaseJIRA from requests.cookies import RequestsCookieJar @@ -77,7 +76,7 @@ def extract_value(self, fields): class JiraConfig(config.ServiceConfig): - service: typing_extensions.Literal['jira'] + service: typing.Literal['jira'] base_uri: pydantic.v1.AnyUrl username: str diff --git a/bugwarrior/services/kanboard.py b/bugwarrior/services/kanboard.py index d5b1bd73..fc249d17 100644 --- a/bugwarrior/services/kanboard.py +++ b/bugwarrior/services/kanboard.py @@ -1,11 +1,11 @@ import datetime import logging import re +import typing from urllib.parse import urlparse from dateutil.tz.tz import tzutc from kanboard import Client -import typing_extensions from bugwarrior import config from bugwarrior.services import Issue, Service @@ -14,7 +14,7 @@ class KanboardConfig(config.ServiceConfig): - service: typing_extensions.Literal['kanboard'] + service: typing.Literal['kanboard'] url: config.StrippedTrailingSlashUrl username: str password: str diff --git a/bugwarrior/services/logseq.py b/bugwarrior/services/logseq.py index cd143c0f..7229d727 100644 --- a/bugwarrior/services/logseq.py +++ b/bugwarrior/services/logseq.py @@ -1,7 +1,7 @@ import logging +import typing import requests -import typing_extensions import re from datetime import datetime @@ -13,7 +13,7 @@ class LogseqConfig(config.ServiceConfig): - service: typing_extensions.Literal["logseq"] + service: typing.Literal["logseq"] host: str = "localhost" port: int = 12315 token: str diff --git a/bugwarrior/services/pagure.py b/bugwarrior/services/pagure.py index ffceb553..2d704fb4 100644 --- a/bugwarrior/services/pagure.py +++ b/bugwarrior/services/pagure.py @@ -1,9 +1,9 @@ import datetime import pytz +import typing import pydantic.v1 import requests -import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue @@ -14,7 +14,7 @@ class PagureConfig(config.ServiceConfig): # strictly required - service: typing_extensions.Literal['pagure'] + service: typing.Literal['pagure'] base_url: config.StrippedTrailingSlashUrl # conditionally required diff --git a/bugwarrior/services/phab.py b/bugwarrior/services/phab.py index 57ae2da1..679b2551 100644 --- a/bugwarrior/services/phab.py +++ b/bugwarrior/services/phab.py @@ -3,7 +3,6 @@ import phabricator import pydantic.v1 -import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue @@ -12,7 +11,7 @@ class PhabricatorConfig(config.ServiceConfig): - service: typing_extensions.Literal['phabricator'] + service: typing.Literal['phabricator'] user_phids: config.ConfigList = config.ConfigList([]) project_phids: config.ConfigList = config.ConfigList([]) diff --git a/bugwarrior/services/pivotaltracker.py b/bugwarrior/services/pivotaltracker.py index d2bd1b89..bf4f814d 100644 --- a/bugwarrior/services/pivotaltracker.py +++ b/bugwarrior/services/pivotaltracker.py @@ -1,9 +1,9 @@ -import re import operator +import re +import typing import requests from jinja2 import Template -import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue, Client @@ -13,12 +13,12 @@ class PivotalTrackerConfig(config.ServiceConfig): - service: typing_extensions.Literal['pivotaltracker'] + service: typing.Literal['pivotaltracker'] user_id: int account_ids: config.ConfigList token: str - version: typing_extensions.Literal['v5', 'edge'] = 'v5' + version: typing.Literal['v5', 'edge'] = 'v5' host: config.StrippedTrailingSlashUrl = config.StrippedTrailingSlashUrl( 'https://www.pivotaltracker.com/services', scheme='https', host='pivotaltracker.com') diff --git a/bugwarrior/services/redmine.py b/bugwarrior/services/redmine.py index 8bc7eafa..00c05a90 100644 --- a/bugwarrior/services/redmine.py +++ b/bugwarrior/services/redmine.py @@ -1,8 +1,8 @@ import requests import re +import typing from taskw import TaskWarriorShellout -import typing_extensions from bugwarrior import config from bugwarrior.services import Issue, Service, Client @@ -15,7 +15,7 @@ class RedMineConfig(config.ServiceConfig): _DEPRECATE_PROJECT_NAME = True project_name: str = '' - service: typing_extensions.Literal['redmine'] + service: typing.Literal['redmine'] url: config.StrippedTrailingSlashUrl key: str diff --git a/bugwarrior/services/taiga.py b/bugwarrior/services/taiga.py index e6298bfb..57f971de 100644 --- a/bugwarrior/services/taiga.py +++ b/bugwarrior/services/taiga.py @@ -1,5 +1,6 @@ +import typing + import requests -import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue, Client, CACHE_REGION as cache @@ -9,7 +10,7 @@ class TaigaConfig(config.ServiceConfig): - service: typing_extensions.Literal['taiga'] + service: typing.Literal['taiga'] base_uri: config.StrippedTrailingSlashUrl auth_token: str diff --git a/bugwarrior/services/teamlab.py b/bugwarrior/services/teamlab.py index 05bb61e8..410c3e02 100644 --- a/bugwarrior/services/teamlab.py +++ b/bugwarrior/services/teamlab.py @@ -1,6 +1,7 @@ +import typing + import pydantic.v1 import requests -import typing_extensions from bugwarrior import config from bugwarrior.services import Issue, Service, Client @@ -13,7 +14,7 @@ class TeamLabConfig(config.ServiceConfig): _DEPRECATE_PROJECT_NAME = True project_name: str = '' - service: typing_extensions.Literal['teamlab'] + service: typing.Literal['teamlab'] hostname: str login: str password: str diff --git a/bugwarrior/services/teamwork_projects.py b/bugwarrior/services/teamwork_projects.py index 8c7d220f..bdf2f5c2 100644 --- a/bugwarrior/services/teamwork_projects.py +++ b/bugwarrior/services/teamwork_projects.py @@ -1,5 +1,6 @@ +import typing + import requests -import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue, Client @@ -9,7 +10,7 @@ class TeamworkConfig(config.ServiceConfig): - service: typing_extensions.Literal['teamwork_projects'] + service: typing.Literal['teamwork_projects'] host: config.StrippedTrailingSlashUrl token: str diff --git a/bugwarrior/services/trac.py b/bugwarrior/services/trac.py index 1ed5d4ab..d0fd5bee 100644 --- a/bugwarrior/services/trac.py +++ b/bugwarrior/services/trac.py @@ -1,10 +1,10 @@ import csv import io as StringIO +import typing import urllib.parse import offtrac import requests -import typing_extensions from bugwarrior import config from bugwarrior.services import Issue, Service @@ -14,7 +14,7 @@ class TracConfig(config.ServiceConfig): - service: typing_extensions.Literal['trac'] + service: typing.Literal['trac'] base_uri: config.NoSchemeUrl scheme: str = 'https' diff --git a/bugwarrior/services/trello.py b/bugwarrior/services/trello.py index 2786480e..97b9bde0 100644 --- a/bugwarrior/services/trello.py +++ b/bugwarrior/services/trello.py @@ -5,15 +5,16 @@ Trello API documentation available at https://developers.trello.com/ """ +import typing + import requests -import typing_extensions from bugwarrior.services import Service, Issue, Client from bugwarrior import config class TrelloConfig(config.ServiceConfig): - service: typing_extensions.Literal['trello'] + service: typing.Literal['trello'] api_key: str token: str diff --git a/bugwarrior/services/versionone.py b/bugwarrior/services/versionone.py index 5a513658..672ec96d 100644 --- a/bugwarrior/services/versionone.py +++ b/bugwarrior/services/versionone.py @@ -1,5 +1,6 @@ +import typing + import pydantic.v1 -import typing_extensions from v1pysdk import V1Meta from v1pysdk.none_deref import NoneDeref from urllib import parse @@ -12,7 +13,7 @@ class VersionOneConfig(config.ServiceConfig): _DEPRECATE_PROJECT_NAME = True project_name: str = '' - service: typing_extensions.Literal['versionone'] + service: typing.Literal['versionone'] base_uri: pydantic.v1.AnyUrl username: str diff --git a/bugwarrior/services/youtrack.py b/bugwarrior/services/youtrack.py index 9dd3a7f9..0f74830e 100644 --- a/bugwarrior/services/youtrack.py +++ b/bugwarrior/services/youtrack.py @@ -2,7 +2,6 @@ import pydantic.v1 import requests -import typing_extensions from bugwarrior import config from bugwarrior.services import Service, Issue, Client @@ -13,7 +12,7 @@ class YoutrackConfig(config.ServiceConfig): - service: typing_extensions.Literal['youtrack'] + service: typing.Literal['youtrack'] host: config.NoSchemeUrl login: str token: str diff --git a/setup.py b/setup.py index a41c0cd8..115d9696 100644 --- a/setup.py +++ b/setup.py @@ -67,8 +67,6 @@ "taskw>=0.8", # Needed for backwards compatibility with python<=3.10. "tomli", - # Needed for backwards compatibility with python<=3.7. - "typing-extensions", ], extras_require={ 'all': list( diff --git a/tests/test_service.py b/tests/test_service.py index f722b334..cb3b0e9f 100644 --- a/tests/test_service.py +++ b/tests/test_service.py @@ -1,7 +1,7 @@ import re +import typing import unittest.mock -import typing_extensions from bugwarrior import config, services from bugwarrior.config import schema @@ -15,7 +15,7 @@ class DumbConfig(config.ServiceConfig): - service: typing_extensions.Literal['test'] + service: typing.Literal['test'] import_labels_as_tags: bool = False label_template: str = '{{label}}'