Skip to content

route_rules.gen ¤

Classes:

ArtifactMeta ¤

Bases: Struct

Parameters:

Attributes:

behavior instance-attribute ¤

behavior: Behavior

format instance-attribute ¤

format: Format

path instance-attribute ¤

path: Path

size instance-attribute ¤

size: int

Builder ¤

Parameters:

  • dist_dir (Path, default: PosixPath('dist') ) –
  • exporters (list[ExporterMihomo], default: [ExporterMihomo(behavior=<Behavior.DOMAIN: 'domain'>, format=<Format.MRS: 'mrs'>, export_path_template='mihomo/{slug}.{behavior}{format.ext}'), ExporterMihomo(behavior=<Behavior.DOMAIN: 'domain'>, format=<Format.TEXT: 'text'>, export_path_template='mihomo/{slug}.{behavior}{format.ext}'), ExporterMihomo(behavior=<Behavior.IPCIDR: 'ipcidr'>, format=<Format.MRS: 'mrs'>, export_path_template='mihomo/{slug}.{behavior}{format.ext}'), ExporterMihomo(behavior=<Behavior.IPCIDR: 'ipcidr'>, format=<Format.TEXT: 'text'>, export_path_template='mihomo/{slug}.{behavior}{format.ext}'), ExporterMihomo(behavior=<Behavior.CLASSICAL: 'classical'>, format=<Format.TEXT: 'text'>, export_path_template='mihomo/{slug}.{behavior}{format.ext}')] ) –
  • recipes (list[RecipeWrapper], default: <dynamic> ) –

    Built-in mutable sequence.

    If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

Methods:

Attributes:

dist_dir class-attribute instance-attribute ¤

dist_dir: Path = field(default=Path('dist'))

exporters class-attribute instance-attribute ¤

exporters: list[ExporterMihomo] = field(
    factory=_default_exporters
)

recipes class-attribute instance-attribute ¤

recipes: list[RecipeWrapper] = field(factory=list)

build async ¤

build() -> None
Source code in src/route_rules/gen/_builder.py
42
43
44
45
46
async def build(self) -> None:
    meta = Meta(build_time=datetime.datetime.now().astimezone())
    for recipe in self.recipes:
        meta.recipes.append(await self.build_recipe(recipe))
    (self.dist_dir / "meta.json").write_bytes(meta.json_encode())

build_recipe async ¤

build_recipe(recipe: RecipeWrapper) -> RecipeMeta
Source code in src/route_rules/gen/_builder.py
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
async def build_recipe(self, recipe: RecipeWrapper) -> RecipeMeta:
    ruleset: RuleSet = await recipe.build()
    meta = RecipeMeta(
        name=recipe.name,
        slug=recipe.slug,
        statistics=await self._build_statistics(recipe, ruleset),
    )
    for provider in recipe.providers:
        meta.providers.append(
            ProviderMeta(
                name=provider,
                download_url=recipe.registry.download_url(provider),
                preview_url=recipe.registry.preview_url(provider),
            )
        )
    for exporter in self.exporters:
        path: Path = exporter.export_path(recipe.slug)
        size: int = exporter.export(self.dist_dir / path, ruleset)
        if size == 0:
            continue
        meta.artifacts.append(
            ArtifactMeta(
                behavior=exporter.behavior,
                format=exporter.format,
                path=path,
                size=size,
            )
        )
    return meta

load classmethod ¤

load(file: str | PathLike[str]) -> Self
Source code in src/route_rules/gen/_builder.py
34
35
36
37
38
39
40
@classmethod
def load(cls, file: str | os.PathLike[str]) -> Self:
    config: Config = Config.load(file)
    self: Self = cls()
    for recipe_config in config.recipes:
        self.recipes.append(RecipeWrapper.from_config(recipe_config))
    return self

Config pydantic-model ¤

Bases: BaseModel

Parameters:

  • recipes (list[RecipeConfig]) –
Show JSON schema:
{
  "$defs": {
    "RecipeConfig": {
      "properties": {
        "name": {
          "title": "Name",
          "type": "string"
        },
        "providers": {
          "items": {
            "type": "string"
          },
          "title": "Providers",
          "type": "array"
        }
      },
      "required": [
        "name",
        "providers"
      ],
      "title": "RecipeConfig",
      "type": "object"
    }
  },
  "properties": {
    "recipes": {
      "items": {
        "$ref": "#/$defs/RecipeConfig"
      },
      "title": "Recipes",
      "type": "array"
    }
  },
  "required": [
    "recipes"
  ],
  "title": "Config",
  "type": "object"
}

Fields:

recipes pydantic-field ¤

recipes: list[RecipeConfig]

load classmethod ¤

load(file: str | PathLike[str]) -> Self
Source code in src/route_rules/gen/_config.py
17
18
19
20
21
@classmethod
def load(cls, file: str | os.PathLike[str]) -> Self:
    file = Path(file)
    data: Any = msgspec.yaml.decode(file.read_bytes())
    return cls.model_validate(data)

Meta ¤

Bases: Struct

Parameters:

  • build_time (datetime) –
  • recipes (list[RecipeMeta], default: <dynamic> ) –

    Built-in mutable sequence.

    If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

Methods:

Attributes:

build_time instance-attribute ¤

build_time: datetime

recipes class-attribute instance-attribute ¤

recipes: list[RecipeMeta] = field(default_factory=list)

json_decode classmethod ¤

json_decode(data: Buffer | str) -> Self
Source code in src/route_rules/gen/_meta.py
41
42
43
@classmethod
def json_decode(cls, data: Buffer | str) -> Self:
    return msgspec.json.decode(data, type=cls, dec_hook=dec_hook)

json_encode ¤

json_encode() -> bytes
Source code in src/route_rules/gen/_meta.py
45
46
def json_encode(self) -> bytes:
    return msgspec.json.encode(self, enc_hook=enc_hook)

ProviderMeta ¤

Bases: Struct

Parameters:

  • name (str) –
  • download_url (str) –
  • preview_url (str) –

Attributes:

download_url instance-attribute ¤

download_url: str

name instance-attribute ¤

name: str

preview_url instance-attribute ¤

preview_url: str

RecipeMeta ¤

Bases: Struct

Parameters:

  • name (str) –
  • slug (str) –
  • artifacts (list[ArtifactMeta], default: <dynamic> ) –

    Built-in mutable sequence.

    If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

  • providers (list[ProviderMeta], default: <dynamic> ) –

    Built-in mutable sequence.

    If no argument is given, the constructor creates a new empty list. The argument must be an iterable if specified.

  • statistics (RecipeStatistics, default: <dynamic> ) –

Attributes:

artifacts class-attribute instance-attribute ¤

artifacts: list[ArtifactMeta] = field(default_factory=list)

name instance-attribute ¤

name: str

providers class-attribute instance-attribute ¤

providers: list[ProviderMeta] = field(default_factory=list)

slug instance-attribute ¤

slug: str

statistics class-attribute instance-attribute ¤

statistics: RecipeStatistics = field(
    default_factory=RecipeStatistics
)

RecipeWrapper ¤

Bases: Recipe

Parameters:

  • name (str) –
  • providers (list[str]) –
  • registry (ProviderRegistry, default: ProviderRegistry(registry={'blackmatrix7': ProviderMihomo(name='blackmatrix7', download_url_template='https://raw.githubusercontent.com/blackmatrix7/ios_rule_script/master/rule/Clash/{name}/{name}.list', preview_url_template='https://github.com/blackmatrix7/ios_rule_script/tree/master/rule/Clash/{name}', _cache=LRUCache({}, maxsize=65536, currsize=0), behavior=<Behavior.CLASSICAL: 'classical'>, format=<Format.TEXT: 'text'>), 'dler-io': ProviderMihomo(name='dler-io', download_url_template='https://raw.githubusercontent.com/dler-io/Rules/main/Clash/Provider/{name}.yaml', preview_url_template='https://github.com/dler-io/Rules/blob/main/Clash/Provider/{name}.yaml', _cache=LRUCache({}, maxsize=65536, currsize=0), behavior=<Behavior.CLASSICAL: 'classical'>, format=<Format.YAML: 'yaml'>), 'MetaCubeX/geosite': ProviderMihomo(name='MetaCubeX/geosite', download_url_template='https://raw.githubusercontent.com/MetaCubeX/meta-rules-dat/meta/geo/geosite/{name}.yaml', preview_url_template='https://github.com/MetaCubeX/meta-rules-dat/blob/meta/geo/geosite/{name}.yaml', _cache=LRUCache({}, maxsize=65536, currsize=0), behavior=<Behavior.DOMAIN: 'domain'>, format=<Format.YAML: 'yaml'>), 'SukkaW/classical': ProviderMihomo(name='SukkaW/classical', download_url_template='https://ruleset.skk.moe/Clash/{name}.txt', preview_url_template='https://ruleset.skk.moe/Clash/{name}.txt', _cache=LRUCache({}, maxsize=65536, currsize=0), behavior=<Behavior.CLASSICAL: 'classical'>, format=<Format.TEXT: 'text'>), 'SukkaW/domain': ProviderMihomo(name='SukkaW/domain', download_url_template='https://ruleset.skk.moe/Clash/{name}.txt', preview_url_template='https://ruleset.skk.moe/Clash/{name}.txt', _cache=LRUCache({}, maxsize=65536, currsize=0), behavior=<Behavior.DOMAIN: 'domain'>, format=<Format.TEXT: 'text'>)}) ) –
  • slug (str, default: <dynamic> ) –

Methods:

Attributes:

name class-attribute instance-attribute ¤

name: str = field()

providers class-attribute instance-attribute ¤

providers: list[str] = field()

registry class-attribute instance-attribute ¤

registry: ProviderRegistry = field(
    factory=presets, kw_only=True
)

slug class-attribute instance-attribute ¤

slug: str = field(
    default=Factory(default_slug, takes_self=True),
    kw_only=True,
)

build async ¤

build() -> RuleSet
Source code in src/route_rules/core/_recipe.py
28
29
30
31
32
33
34
@cta.cachedmethod(lambda self: self._cache)
async def build(self) -> RuleSet:
    ruleset: RuleSet = RuleSet.union(
        *(await asyncio.gather(*(self.registry.load(p) for p in self.providers)))
    )
    ruleset = ruleset.optimize()
    return ruleset

from_config classmethod ¤

from_config(config: RecipeConfig) -> Self
Source code in src/route_rules/gen/_recipe.py
12
13
14
@classmethod
def from_config(cls, config: RecipeConfig) -> Self:
    return cls(name=config.name, providers=config.providers)