Skip to content

Commit

Permalink
Add Ruff; init tests; fix code style and type hints (#45)
Browse files Browse the repository at this point in the history
  • Loading branch information
MarshalX committed May 26, 2023
1 parent cd9e351 commit 80c140e
Show file tree
Hide file tree
Showing 41 changed files with 563 additions and 510 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/black.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ jobs:

steps:
- name: Checkout repository.
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Setup Python.
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: 3.7

Expand Down
29 changes: 29 additions & 0 deletions .github/workflows/ruff.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Ruff

on: [ pull_request, push ]

jobs:
ruff:
runs-on: ubuntu-latest

steps:
- name: Checkout repository.
uses: actions/checkout@v3

- name: Setup Python.
uses: actions/setup-python@v4
with:
python-version: 3.7

- name: Install dependencies.
run: pip install black

- name: Run linter check on package.
uses: chartboost/ruff-action@v1
with:
src: "./atproto"

- name: Run linter check on tests.
uses: chartboost/ruff-action@v1
with:
src: "./tests"
25 changes: 25 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Unit Tests

on: [ pull_request, push ]

jobs:
unit_tests:
runs-on: ubuntu-latest

steps:
- name: Checkout repository.
uses: actions/checkout@v3

- name: Set up Python.
uses: actions/setup-python@v4
with:
python-version: '3.7'

- name: Setup Poetry.
uses: snok/install-poetry@v1

- name: Install dependencies.
run: poetry install

- name: Run Tests.
run: poetry run pytest
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ coverage.xml

# Sphinx documentation
docs/_build/

.ruff_cache/
8 changes: 4 additions & 4 deletions atproto/car/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import typing as t
from io import BytesIO

from .. import cbor, leb128
from ..cid import CID
from atproto import cbor, leb128
from atproto.cid import CID

Blocks = t.Dict[CID, dict]

Expand All @@ -12,12 +12,12 @@ class CAR:

_CID_V1_BYTES_LEN = 36

def __init__(self, root: str, blocks: Blocks):
def __init__(self, root: str, blocks: Blocks) -> None:
self._root = root
self._blocks = blocks

@property
def root(self):
def root(self) -> str:
"""Get root."""
return self._root

Expand Down
4 changes: 2 additions & 2 deletions atproto/cbor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
class _BytesReadCounter:
_num_bytes_read = 0

def __call__(self, _, num_bytes_read: int):
def __call__(self, _, num_bytes_read: int) -> None:
self._num_bytes_read += num_bytes_read

def __int__(self) -> int:
return self._num_bytes_read


def decode_dag(data: DagCborData, *, allow_concat=False, callback=None) -> _dag_cbor.IPLDKind:
def decode_dag(data: DagCborData, *, allow_concat: bool = False, callback=None) -> _dag_cbor.IPLDKind:
"""Decodes and returns a single data item from the given data, with the DAG-CBOR codec.
Args:
Expand Down
38 changes: 23 additions & 15 deletions atproto/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import typing as t
from pathlib import Path

import click
Expand All @@ -11,18 +12,23 @@
class AliasedGroup(click.Group):
"""Ref: https://click.palletsprojects.com/en/8.1.x/advanced/"""

def get_command(self, ctx, cmd_name):
def get_command(self, ctx: click.Context, cmd_name: str) -> t.Optional[click.Command]:
rv = click.Group.get_command(self, ctx, cmd_name)
if rv is not None:
return rv

matches = [x for x in self.list_commands(ctx) if x.startswith(cmd_name)]
if not matches:
return None
elif len(matches) == 1:
if len(matches) == 1:
return click.Group.get_command(self, ctx, matches[0])

ctx.fail(f'Too many matches: {", ".join(sorted(matches))}')
return None

def resolve_command(self, ctx, args):
def resolve_command(
self, ctx: click.Context, args: t.List[str]
) -> t.Tuple[t.Optional[str], t.Optional[click.Command], t.List[str]]:
# always return the full command name
_, cmd, args = super().resolve_command(ctx, args)
return cmd.name, cmd, args
Expand All @@ -31,23 +37,23 @@ def resolve_command(self, ctx, args):
@click.group(cls=AliasedGroup)
@click.version_option(__version__)
@click.pass_context
def atproto_cli(ctx: click.Context):
def atproto_cli(ctx: click.Context) -> None:
"""CLI of AT Protocol SDK for Python"""
ctx.ensure_object(dict)


@atproto_cli.group(cls=AliasedGroup)
@click.option('--lexicon-dir', type=click.Path(exists=True), default=None, help='Path to dir with .JSON lexicon files.')
@click.pass_context
def gen(ctx: click.Context, lexicon_dir):
def gen(ctx: click.Context, lexicon_dir: t.Optional[str]) -> None:
if lexicon_dir:
lexicon_dir = Path(lexicon_dir)
ctx.obj['lexicon_dir'] = lexicon_dir


@gen.command(name='all', help='Generated models, namespaces, and async clients with default configs.')
@click.pass_context
def gen_all(_: click.Context):
def gen_all(_: click.Context) -> None:
click.echo('Generating all:')

click.echo('- models...')
Expand All @@ -60,26 +66,26 @@ def gen_all(_: click.Context):
click.echo('Done!')


def _gen_models(lexicon_dir=None, output_dir=None):
generate_models(lexicon_dir, output_dir)
def _gen_models(*args) -> None:
generate_models(*args)


def _gen_namespaces(lexicon_dir=None, output_dir=None, async_filename=None, sync_filename=None):
generate_namespaces(lexicon_dir, output_dir, async_filename, sync_filename)
def _gen_namespaces(*args) -> None:
generate_namespaces(*args)


def _gen_async_version():
def _gen_async_version() -> None:
gen_client('client.py', 'async_client.py')


@gen.command(name='models')
@click.option('--output-dir', type=click.Path(exists=True), default=None)
@click.pass_context
def gen_models(ctx: click.Context, output_dir):
def gen_models(ctx: click.Context, output_dir: t.Optional[str]) -> None:
click.echo('Generating models...')

if output_dir:
# FIXME(MarshalX)
# FIXME(MarshalX): remove hardcoded imports
output_dir = Path(output_dir)
click.secho(
"It doesn't work with '--output-dir' option very well because of hardcoded imports! Replace by yourself",
Expand All @@ -96,7 +102,9 @@ def gen_models(ctx: click.Context, output_dir):
@click.option('--async-filename', type=click.STRING, default=None, help='Should end with ".py".')
@click.option('--sync-filename', type=click.STRING, default=None, help='Should end with ".py".')
@click.pass_context
def gen_namespaces(ctx: click.Context, output_dir, async_filename, sync_filename):
def gen_namespaces(
ctx: click.Context, output_dir: t.Optional[str], async_filename: t.Optional[str], sync_filename: t.Optional[str]
) -> None:
click.echo('Generating namespaces...')

if output_dir:
Expand All @@ -109,7 +117,7 @@ def gen_namespaces(ctx: click.Context, output_dir, async_filename, sync_filename

@gen.command(name='async')
@click.pass_context
def gen_async_version(_: click.Context):
def gen_async_version(_: click.Context) -> None:
click.echo('Generating async clients...')
_gen_async_version()
click.echo('Done!')
Expand Down
16 changes: 9 additions & 7 deletions atproto/codegen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from atproto.nsid import NSID

DISCLAIMER = [
'# THIS IS THE AUTO-GENERATED CODE. DON\'T EDIT IT BY HANDS!',
"# THIS IS THE AUTO-GENERATED CODE. DON'T EDIT IT BY HANDS!",
'# Copyright (C) 2023 Ilya (Marshal) <https://github.com/MarshalX>.',
'# This file is part of Python atproto SDK. Licenced under MIT.',
]
Expand All @@ -20,8 +20,11 @@


def format_code(filepath: Path) -> None:
subprocess.run(['black', '--quiet', filepath])
subprocess.run(['isort', '--quiet', filepath])
if not isinstance(filepath, Path):
return

subprocess.run(['ruff', '--quiet', '--fix', filepath]) # noqa: S603, S607
subprocess.run(['black', '--quiet', filepath]) # noqa: S603, S607


def append_code(filepath: Path, code: str) -> None:
Expand Down Expand Up @@ -53,8 +56,7 @@ def get_import_path_old(nsid: NSID) -> str:

def get_import_path(nsid: NSID) -> str:
nsid_parts = nsid.segments[:-1] + camel_case_split(nsid.name)
alias_name = ''.join([p.capitalize() for p in nsid_parts])
return alias_name
return ''.join([p.capitalize() for p in nsid_parts])


def convert_camel_case_to_snake_case(string: str) -> str:
Expand Down Expand Up @@ -96,8 +98,8 @@ def get_sync_async_keywords(*, sync: bool) -> t.Tuple[str, str]:

def capitalize_first_symbol(string: str) -> str:
if string and string[0].islower():
chars = [c for c in string[1:]]
chars = list(string[1:])
chars.insert(0, string[0].upper())
string = ''.join(chars)
return ''.join(chars)

return string
4 changes: 2 additions & 2 deletions atproto/codegen/models/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@
class _LexiconDir:
dir_path: t.Optional[Path]

def __init__(self, default_path: Path = None):
def __init__(self, default_path: Path = None) -> None:
self.dir_path = default_path

def set(self, path: Path):
def set(self, path: Path) -> None:
self.dir_path = path

def get(self) -> Path:
Expand Down
Loading

0 comments on commit 80c140e

Please sign in to comment.