class MyDataclass: a: int b: t.Optional[str] = dataclasses.field(default=None, metadata={'alias': 'balias'}) c: te.Annotated[str, A.alias('calias')] = 42 d: t.Optional[P] = None e: str = dataclasses.field(default='foobar', init=False)
class DefaultRepositoryConfig: #: A list of paths pointing to projects to include in the application invokation. This is useful if multiple #: projects should be usable with the Slam CLI in unison. Note that if this option is not set and either no #: configuration file exists in the CWD or the `slam.toml` is used, all immediate subdirectories that contain #: a `pyproject.toml` will be considered included projects. include: list[str] | None = None #: The repository hosting service. If not specified, it will be detected automatically. repository_host: t.Annotated[RepositoryHost | None, alias('repository-host')] = None
def dataclass_to_schema( dataclass_type: t.Type, type_hint_adapter: t.Optional[TypeHintAdapter] = None) -> Schema: """ Converts the given *dataclass_type* to a #Schema. The dataclass fields are converted to #BaseType#s via the given *type_hint_adapter*. If no adapter is specified, the #DefaultTypeHintAdapter will be used (note that this adapter does _not_ expand #ConcreteType#s of dataclasses to #ObjectType#s). """ preconditions.check_instance_of(dataclass_type, type) preconditions.check_argument(is_dataclass(dataclass_type), 'expected @dataclass type') if type_hint_adapter is None: type_hint_adapter = DefaultTypeHintAdapter() fields: t.Dict[str, Field] = {} annotations = get_type_hints(dataclass_type) resolver = ModuleForwardReferenceResolver( sys.modules[dataclass_type.__module__]) for field in _get_fields(dataclass_type): if not field.init: # If we cannot initialize the field in the constructor, we should also # exclude it from the definition of the type for de-/serializing. continue # NOTE (NiklasRosenstein): We do not use #field.type because if it contains a #t.ForwardRef, # it will not be resolved and we can't convert that to our type representation. field_type_hint = type_hint_adapter.adapt_type_hint( annotations[field.name], None, resolver) field_annotations = list( field.metadata.get(ANNOTATIONS_METADATA_KEY, [])) # Handle field(metadata={'alias': ...}). The value can be a string or list of strings. if not any(isinstance(x, A.alias) for x in field_annotations): if 'alias' in field.metadata: aliases = field.metadata['alias'] if isinstance(aliases, str): aliases = [aliases] field_annotations.append(A.alias(*aliases)) field_default_factory = field.default_factory # type: ignore fields[field.name] = Field( field.name, field_type_hint, field_annotations, NotSet.Value if field.default == _MISSING else field.default, NotSet.Value if field_default_factory == _MISSING else field_default_factory) return Schema( dataclass_type.__name__, fields, list(A.get_type_annotations(dataclass_type).values()), dataclass_type, )
class ProjectConfig: #: The name of the project handler plugin. If none is specified, the built-in project handlers are tested #: (see the #slam.ext.project_handlers module for more info on those). handler: str | None = None #: The source directory to use when relying on automatic package detection. If not set, the default project #: handler will search in `"src/"`` and then `"./"``. source_directory: t.Annotated[str | None, alias('source-directory')] = None #: Whether the project source code is inteded to be typed. typed: bool | None = None
class SpdxLicense: reference: str is_deprecated_license_id: t.Annotated[bool, alias('isDeprecatedLicenseId')] details_url: t.Annotated[str, alias('detailsUrl')] reference_number: t.Annotated[int, alias('referenceNumber')] name: str license_id: t.Annotated[str, alias('licenseId')] see_also: t.Annotated[list[str], alias('seeAlso')] is_osi_approved: t.Annotated[bool, alias('isOsiApproved')] is_fsf_libre: t.Annotated[bool | None, alias('isFsfLibre')] = None
def test_dataclass_to_schema_conversion(): @dataclasses.dataclass class P: pass @dataclasses.dataclass class MyDataclass: a: int b: t.Optional[str] = dataclasses.field(default=None, metadata={'alias': 'balias'}) c: te.Annotated[str, A.alias('calias')] = 42 d: t.Optional[P] = None e: str = dataclasses.field(default='foobar', init=False) #schema = dataclass_to_schema(MyDataclass) type_ = from_typing(MyDataclass) assert isinstance(type_, ObjectType) assert type_.schema == Schema( 'MyDataclass', { 'a': Field('a', ConcreteType(int)), 'b': Field('b', OptionalType(ConcreteType(str)), [A.alias('balias')], default=None), 'c': Field('c', ConcreteType(str, [A.alias('calias')]), [], default=42), 'd': Field('d', OptionalType(ObjectType(dataclass_to_schema(P, mapper))), default=None), }, [], MyDataclass, )
def test_enum_converter(): assert mapper().serialize(Color.RED, Color) == 'RED' assert mapper().deserialize('RED', Color) == Color.RED assert mapper().serialize(Color.BLUE, Color) == 'ImBlue' assert mapper().deserialize('ImBlue', Color) == Color.BLUE assert mapper().deserialize('BLUE', Color) == Color.BLUE m = mapper() m.add_field_annotation(Color, 'GREEN', A.alias('greeeeen')) assert m.serialize(Color.RED, Color) == 'RED' assert m.serialize(Color.GREEN, Color) == 'greeeeen' assert m.deserialize('GREEN', Color) == Color.GREEN assert m.deserialize('greeeeen', Color) == Color.GREEN
class ChangelogConfig: #: Whether the changelog feature is enabled. This acts locally for the current project and not globally. #: Particularly useful for monorepos that have multiple subprojects each with their changelog directories #: to prevent accidentally creating changelogs in the root directory. #: #: When not set, it will be considered `True` if the current project is a Python project. enabled: bool | None = None #: The directory in which changelogs are stored. directory: Path = Path('.changelog') #: The list of valid types that can be used in changelog entries. The default types are #: #DEFAULT_CHANGELOG_TYPES. valid_types: t.Annotated[ list[str] | None, alias('valid-types')] = dataclasses.field( default_factory=lambda: list(DEFAULT_VALID_TYPES))
class Changelog: entries: list[ChangelogEntry] = dataclasses.field(default_factory=list) release_date: t.Annotated[datetime.date | None, alias("release-date")] = None
class DejaCodeLicense: license_text: str key: t.Annotated[str, alias('Key')] name: t.Annotated[str, alias('Name')] short_name: t.Annotated[str, alias('Short Name')] category: t.Annotated[str, alias('Category')] license_type: t.Annotated[str, alias('License type')] license_profile: t.Annotated[str, alias('License profile')] license_style: t.Annotated[str, alias('License style')] owner: t.Annotated[str, alias('Owner')] spdx_short_identifier: t.Annotated[str, alias('SPDX short identifier')] keywords: t.Annotated[str, alias('Keywords')] standard_notice: t.Annotated[str | None, alias('Standard notice')] special_obligations: t.Annotated[str | None, alias('Special obligations')] publication_year: t.Annotated[int, alias('Publication year')] urn: t.Annotated[str, alias('URN')] dataspace: t.Annotated[str, alias('Dataspace')] homepage_url: t.Annotated[str, alias('Homepage URL')] text_urls: t.Annotated[str, alias('Text URLs')] osi_url: t.Annotated[str, alias('OSI URL')] faq_url: t.Annotated[str, alias('FAQ URL')] guidance_url: t.Annotated[str | None, alias('Guidance URL')] other_urls: t.Annotated[str, alias('Other URLs')]
class Color(enum.Enum): RED = 0 GREEN = 1 BLUE: te.Annotated[int, A.alias('ImBlue')] = 2
class ApplicationConfig: #: A list of application plugins to _not_ activate. disable: list[str] = dataclasses.field(default_factory=list) #: A list of plugins to enable only, causing the default plugins to not be loaded. enable_only: t.Annotated[list[str] | None, alias('enable-only')] = None