Skip to content

Commit ddee526

Browse files
committed
Drop support for Python 3.8
1 parent 0391e8c commit ddee526

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+492
-623
lines changed

.github/workflows/ci-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
strategy:
2121
matrix:
2222
py-ver-major: [3]
23-
py-ver-minor: [8, 9, 10, 11, 12, 13]
23+
py-ver-minor: [9, 10, 11, 12, 13]
2424
fail-fast: false
2525

2626
env:

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Style guide:
2-
- Python 3.8+ compatible code
2+
- Python 3.9+ compatible code
33
- PEP-484 type hints
44
- Prefer new style format strings https://pyformat.info/
55
- Use ``make format`` to format your code
@@ -19,6 +19,6 @@ Here's a rough guide (improvements are welcome!)
1919
- Check the version which might be different from the version installed in general on any system: ``schema-salad-tool --version``
2020
- After you've made the changes, you can the complete test suite via tox: ``tox``
2121
- If you want to run specific tests, say ``unit tests`` in Python 3.5, then: ``tox -e py35-unit``.
22-
- Look at ``tox.ini`` for all available tests and runtimes
22+
- Look at ``tox -l`` for all available tests and runtimes
2323
- If tests are passing, you can simply commit and create a PR on ``schema_salad`` repo:
2424
- After you're done working, you can deactivate the virtual environment: ``deactivate``

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ bandit:
205205
bandit --recursive --exclude schema_salad/tests/ schema_salad
206206

207207
pyupgrade: $(filter-out schema_salad/metaschema.py,$(PYSOURCES))
208-
pyupgrade --exit-zero-even-if-changed --py38-plus $^
208+
pyupgrade --exit-zero-even-if-changed --py39-plus $^
209209
auto-walrus $^
210210

211211
release-test: FORCE

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ generation, and transformation to RDF_. Salad provides a bridge
2323
between document and record oriented data modeling and the Semantic
2424
Web.
2525

26-
The Schema Salad library is Python 3.8+ only.
26+
The Schema Salad library is Python 3.9+ only.
2727

2828
Installation
2929
------------

pyproject.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ requires = [
66
"black>=19.10b0,<23.12",
77
"types-requests",
88
"types-dataclasses",
9-
"importlib_resources>=1.4;python_version<'3.9'",
109
"ruamel.yaml>=0.17.6, < 0.19",
1110
"types-setuptools",
1211
"CacheControl[filecache] >= 0.13.1, < 0.15"
@@ -28,4 +27,4 @@ environment = { SCHEMA_SALAD_USE_MYPYC="1", MYPYPATH="$(pwd)/mypy-stubs" }
2827

2928
[tool.black]
3029
line-length = 100
31-
target-version = [ "py38" ]
30+
target-version = [ "py39" ]

requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,3 @@ mistune>=3,<3.1
55
CacheControl[filecache]>= 0.11.7, < 0.15
66
black>=19.10b0,<24.11
77
mypy_extensions
8-
importlib_resources>=1.4;python_version<'3.9'

schema_salad/avro/schema.py

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
A boolean; or
3232
Null.
3333
"""
34-
from typing import Any, Dict, List, Optional, Tuple, Union, cast
34+
from typing import Any, Optional, Union, cast
3535

3636
from mypy_extensions import mypyc_attr
3737

@@ -63,13 +63,13 @@
6363
# MappingDataType = Dict[str, Union[PropType, List[PropsType]]]
6464
# was: Union[str, MappingDataType, List[MappingDataType]]
6565
JsonDataType = Any
66-
AtomicPropType = Union[None, str, int, float, bool, "Schema", List[str], List["Field"]]
66+
AtomicPropType = Union[None, str, int, float, bool, "Schema", list[str], list["Field"]]
6767
PropType = Union[
6868
AtomicPropType,
69-
Dict[str, AtomicPropType],
70-
List[Dict[str, AtomicPropType]],
69+
dict[str, AtomicPropType],
70+
list[dict[str, AtomicPropType]],
7171
]
72-
PropsType = Dict[str, PropType]
72+
PropsType = dict[str, PropType]
7373

7474
FIELD_RESERVED_PROPS = ("default", "name", "doc", "order", "type")
7575

@@ -189,7 +189,7 @@ class Names:
189189
"""Track name set and default namespace during parsing."""
190190

191191
def __init__(self, default_namespace: Optional[str] = None) -> None:
192-
self.names: Dict[str, NamedSchema] = {}
192+
self.names: dict[str, NamedSchema] = {}
193193
self.default_namespace = default_namespace
194194

195195
def has_name(self, name_attr: str, space_attr: Optional[str]) -> bool:
@@ -281,7 +281,7 @@ def __init__(
281281
default: Optional[Any] = None,
282282
order: Optional[str] = None,
283283
names: Optional[Names] = None,
284-
doc: Optional[Union[str, List[str]]] = None,
284+
doc: Optional[Union[str, list[str]]] = None,
285285
other_props: Optional[PropsType] = None,
286286
) -> None:
287287
# Ensure valid ctor args
@@ -361,9 +361,9 @@ def __init__(
361361
self,
362362
name: str,
363363
namespace: Optional[str],
364-
symbols: List[str],
364+
symbols: list[str],
365365
names: Optional[Names] = None,
366-
doc: Optional[Union[str, List[str]]] = None,
366+
doc: Optional[Union[str, list[str]]] = None,
367367
other_props: Optional[PropsType] = None,
368368
) -> None:
369369
# Ensure valid ctor args
@@ -384,8 +384,8 @@ def __init__(
384384

385385
# read-only properties
386386
@property
387-
def symbols(self) -> List[str]:
388-
return cast(List[str], self.get_prop("symbols"))
387+
def symbols(self) -> list[str]:
388+
return cast(list[str], self.get_prop("symbols"))
389389

390390

391391
#
@@ -473,7 +473,7 @@ def __init__(
473473
names: Names,
474474
name: str,
475475
namespace: Optional[str] = None,
476-
doc: Optional[Union[str, List[str]]] = None,
476+
doc: Optional[Union[str, list[str]]] = None,
477477
other_props: Optional[PropsType] = None,
478478
) -> None:
479479
"""Create a NamedMapSchema object."""
@@ -505,8 +505,8 @@ def values(self) -> Schema:
505505
return cast(Schema, self.get_prop("values"))
506506

507507

508-
def _build_schema_objects(schemas: List[JsonDataType], names: Names) -> List[Schema]:
509-
schema_objects: List[Schema] = []
508+
def _build_schema_objects(schemas: list[JsonDataType], names: Names) -> list[Schema]:
509+
schema_objects: list[Schema] = []
510510
for schema in schemas:
511511
if isinstance(schema, str) and names.has_name(schema, None):
512512
new_schema = cast(Schema, names.get_name(schema, None))
@@ -536,7 +536,7 @@ class UnionSchema(Schema):
536536

537537
def __init__(
538538
self,
539-
schemas: List[JsonDataType],
539+
schemas: list[JsonDataType],
540540
names: Names,
541541
) -> None:
542542
"""
@@ -558,7 +558,7 @@ def __init__(
558558

559559
# read-only properties
560560
@property
561-
def schemas(self) -> List[Schema]:
561+
def schemas(self) -> list[Schema]:
562562
"""Avro schemas composing the Union type."""
563563
return self._schemas
564564

@@ -568,11 +568,11 @@ class NamedUnionSchema(NamedSchema):
568568

569569
def __init__(
570570
self,
571-
schemas: List[JsonDataType],
571+
schemas: list[JsonDataType],
572572
names: Names,
573573
name: str,
574574
namespace: Optional[str] = None,
575-
doc: Optional[Union[str, List[str]]] = None,
575+
doc: Optional[Union[str, list[str]]] = None,
576576
):
577577
"""
578578
Initialize a new NamedUnionSchema.
@@ -595,16 +595,16 @@ def __init__(
595595

596596
# read-only properties
597597
@property
598-
def schemas(self) -> List[Schema]:
598+
def schemas(self) -> list[Schema]:
599599
return self._schemas
600600

601601

602602
class RecordSchema(NamedSchema):
603603
@staticmethod
604-
def make_field_objects(field_data: List[PropsType], names: Names) -> List[Field]:
604+
def make_field_objects(field_data: list[PropsType], names: Names) -> list[Field]:
605605
"""We're going to need to make message parameters too."""
606-
field_objects: List[Field] = []
607-
parsed_fields: Dict[str, PropsType] = {}
606+
field_objects: list[Field] = []
607+
parsed_fields: dict[str, PropsType] = {}
608608
for field in field_data:
609609
if hasattr(field, "get") and callable(field.get):
610610
atype = field.get("type")
@@ -622,7 +622,7 @@ def make_field_objects(field_data: List[PropsType], names: Names) -> List[Field]
622622
doc = field.get("doc")
623623
if not (doc is None or isinstance(doc, (list, str))):
624624
raise SchemaParseException('"doc" must be a string, list of strings, or None')
625-
doc = cast(Union[str, List[str], None], doc)
625+
doc = cast(Union[str, list[str], None], doc)
626626
other_props = get_other_props(field, FIELD_RESERVED_PROPS)
627627
new_field = Field(atype, name, has_default, default, order, names, doc, other_props)
628628
parsed_fields[new_field.name] = field
@@ -635,10 +635,10 @@ def __init__(
635635
self,
636636
name: str,
637637
namespace: Optional[str],
638-
fields: List[PropsType],
638+
fields: list[PropsType],
639639
names: Names,
640640
schema_type: str = "record",
641-
doc: Optional[Union[str, List[str]]] = None,
641+
doc: Optional[Union[str, list[str]]] = None,
642642
other_props: Optional[PropsType] = None,
643643
) -> None:
644644
# Ensure valid ctor args
@@ -663,14 +663,14 @@ def __init__(
663663

664664
# read-only properties
665665
@property
666-
def fields(self) -> List[Field]:
667-
return cast(List[Field], self.get_prop("fields"))
666+
def fields(self) -> list[Field]:
667+
return cast(list[Field], self.get_prop("fields"))
668668

669669

670670
#
671671
# Module Methods
672672
#
673-
def get_other_props(all_props: PropsType, reserved_props: Tuple[str, ...]) -> Optional[PropsType]:
673+
def get_other_props(all_props: PropsType, reserved_props: tuple[str, ...]) -> Optional[PropsType]:
674674
"""
675675
Retrieve the non-reserved properties from a dictionary of properties.
676676
@@ -690,7 +690,7 @@ def make_avsc_object(json_data: JsonDataType, names: Optional[Names] = None) ->
690690
if names is None:
691691
names = Names()
692692

693-
if isinstance(json_data, Dict) and json_data.get("name") == "org.w3id.cwl.salad.Any":
693+
if isinstance(json_data, dict) and json_data.get("name") == "org.w3id.cwl.salad.Any":
694694
del names.names["org.w3id.cwl.salad.Any"]
695695
elif not names.has_name("org.w3id.cwl.salad.Any", None):
696696
EnumSchema("org.w3id.cwl.salad.Any", None, ["Any"], names=names)
@@ -723,15 +723,15 @@ def make_avsc_object(json_data: JsonDataType, names: Optional[Names] = None) ->
723723
raise SchemaParseException(
724724
f'"symbols" for type enum must be a list of strings: {json_data}'
725725
)
726-
symbols = cast(List[str], symbols)
726+
symbols = cast(list[str], symbols)
727727
return EnumSchema(name, namespace, symbols, names, doc, other_props)
728728
if atype in ["record", "error"]:
729729
fields = json_data.get("fields", [])
730730
if not isinstance(fields, list):
731731
raise SchemaParseException(
732732
f'"fields" for type {atype} must be a list of mappings: {json_data}'
733733
)
734-
fields = cast(List[PropsType], fields)
734+
fields = cast(list[PropsType], fields)
735735
return RecordSchema(name, namespace, fields, names, atype, doc, other_props)
736736
raise SchemaParseException(f"Unknown Named Type: {atype}")
737737
if atype in VALID_TYPES:
@@ -774,7 +774,7 @@ def make_avsc_object(json_data: JsonDataType, names: Optional[Names] = None) ->
774774
raise SchemaParseException(fail_msg)
775775

776776

777-
def is_subtype(types: Dict[str, Any], existing: PropType, new: PropType) -> bool:
777+
def is_subtype(types: dict[str, Any], existing: PropType, new: PropType) -> bool:
778778
"""Check if a new type specification is compatible with an existing type spec."""
779779
if existing == new:
780780
return True
@@ -804,9 +804,9 @@ def is_subtype(types: Dict[str, Any], existing: PropType, new: PropType) -> bool
804804
if existing.get("type") == "enum" and new.get("type") == "enum":
805805
return is_subtype(types, existing["symbols"], new["symbols"])
806806
if existing.get("type") == "record" and new.get("type") == "record":
807-
for new_field in cast(List[Dict[str, Any]], new["fields"]):
807+
for new_field in cast(list[dict[str, Any]], new["fields"]):
808808
new_field_missing = True
809-
for existing_field in cast(List[Dict[str, Any]], existing["fields"]):
809+
for existing_field in cast(list[dict[str, Any]], existing["fields"]):
810810
if new_field["name"] == existing_field["name"]:
811811
if not is_subtype(types, existing_field["type"], new_field["type"]):
812812
return False

schema_salad/codegen.py

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
11
"""Generate language specific loaders for a particular SALAD schema."""
22

33
import sys
4+
from collections.abc import MutableMapping, MutableSequence
45
from io import TextIOWrapper
5-
from typing import (
6-
Any,
7-
Dict,
8-
List,
9-
MutableMapping,
10-
MutableSequence,
11-
Optional,
12-
TextIO,
13-
Union,
14-
)
6+
from typing import Any, Optional, TextIO, Union
157
from urllib.parse import urlsplit
168

179
from . import schema
@@ -32,14 +24,14 @@
3224

3325
def codegen(
3426
lang: str,
35-
i: List[Dict[str, str]],
36-
schema_metadata: Dict[str, Any],
27+
i: list[dict[str, str]],
28+
schema_metadata: dict[str, Any],
3729
loader: Loader,
3830
target: Optional[str] = None,
3931
examples: Optional[str] = None,
4032
package: Optional[str] = None,
4133
copyright: Optional[str] = None,
42-
spdx_copyright_text: Optional[List[str]] = None,
34+
spdx_copyright_text: Optional[list[str]] = None,
4335
spdx_license_identifier: Optional[str] = None,
4436
parser_info: Optional[str] = None,
4537
) -> None:

schema_salad/codegen_base.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
"""Base class for the generation of loaders from schema-salad definitions."""
22

33
from collections import OrderedDict
4-
from typing import Any, Dict, List, MutableSequence, Optional, Set, Union
4+
from collections.abc import MutableSequence
5+
from typing import Any, Optional, Union
56

67

78
class TypeDef: # pylint: disable=too-few-public-methods
@@ -66,7 +67,7 @@ class CodeGenBase:
6667
def __init__(self) -> None:
6768
self.collected_types: OrderedDict[str, TypeDef] = OrderedDict()
6869
self.lazy_inits: OrderedDict[str, LazyInitDef] = OrderedDict()
69-
self.vocab: Dict[str, str] = {}
70+
self.vocab: dict[str, str] = {}
7071

7172
def declare_type(self, declared_type: TypeDef) -> TypeDef:
7273
"""Add this type to our collection, if needed."""
@@ -99,18 +100,18 @@ def begin_class(
99100
abstract: bool,
100101
field_names: MutableSequence[str],
101102
idfield: str,
102-
optional_fields: Set[str],
103+
optional_fields: set[str],
103104
) -> None:
104105
"""Produce the header for the given class."""
105106
raise NotImplementedError()
106107

107-
def end_class(self, classname: str, field_names: List[str]) -> None:
108+
def end_class(self, classname: str, field_names: list[str]) -> None:
108109
"""Signal that we are done with this class."""
109110
raise NotImplementedError()
110111

111112
def type_loader(
112113
self,
113-
type_declaration: Union[List[Any], Dict[str, Any]],
114+
type_declaration: Union[list[Any], dict[str, Any]],
114115
container: Optional[str] = None,
115116
no_link_check: Optional[bool] = None,
116117
) -> TypeDef:

0 commit comments

Comments
 (0)