Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add cross_sync #999

Open
wants to merge 260 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
260 commits
Select commit Hold shift + click to select a range
70fd731
keep docstrings on pass
daniel-sanche Apr 9, 2024
5c96cd3
improved import replacement code
daniel-sanche Apr 10, 2024
86b2e25
renamed the two types of replacements
daniel-sanche Apr 10, 2024
db16d0f
use concrete names in generator
daniel-sanche Apr 10, 2024
8c9676d
fixed import paths
daniel-sanche Apr 10, 2024
d4ca864
avoid circular import
daniel-sanche Apr 10, 2024
2d7b88f
improved string typing
daniel-sanche Apr 10, 2024
2c950f2
got client and table working
daniel-sanche Apr 10, 2024
f73a225
moved config into yaml file
daniel-sanche Apr 11, 2024
92d5608
moved save_path into yaml
daniel-sanche Apr 11, 2024
7b40f27
fixed sync emulator channel
daniel-sanche Apr 11, 2024
b3546d8
moved acceptance tests to async folder
daniel-sanche Apr 11, 2024
cbec8f2
broke module_replacements into asyncio and imports
daniel-sanche Apr 11, 2024
1af60be
update retries_async
daniel-sanche Apr 11, 2024
e486ad5
replaced asyncio.Task
daniel-sanche Apr 11, 2024
1974a50
removed use of async generator
daniel-sanche Apr 11, 2024
64ec3d5
fixed type issue
daniel-sanche Apr 11, 2024
f67ebc4
got _mutate_rows tests passing
daniel-sanche Apr 11, 2024
2ebbb72
got sync read_rows tests passing
daniel-sanche Apr 11, 2024
0bfb257
got flow control tests passing
daniel-sanche Apr 12, 2024
5b9e967
made some fixes to mutations batcher
daniel-sanche Apr 12, 2024
717c401
improved modularity of mutation batcher tests
daniel-sanche Apr 12, 2024
aa472c1
fixed TableAssync references
daniel-sanche Apr 12, 2024
06f0586
added event for batcher lock
daniel-sanche Apr 12, 2024
d097aa1
got mutation batcher tests passing
daniel-sanche Apr 12, 2024
8df5920
did some refactoring of client tests
daniel-sanche Apr 13, 2024
dcc0ab6
added sharded read rows sync
daniel-sanche Apr 13, 2024
10c565f
made tweaks to read rows sharded
daniel-sanche Apr 13, 2024
2cdf0ab
got client tests passing
daniel-sanche Apr 16, 2024
ef892bc
moved more logic into generated portion
daniel-sanche Apr 16, 2024
fe572bc
got table tests passing
daniel-sanche Apr 16, 2024
1d428a6
got all client tests passing
daniel-sanche Apr 16, 2024
751c676
fixed slow test
daniel-sanche Apr 17, 2024
97f4797
got async read_rows acceptance working again
daniel-sanche Apr 17, 2024
92f2132
got acceptance tests working
daniel-sanche Apr 17, 2024
c006482
ran blacken
daniel-sanche Apr 17, 2024
c39d26a
fixed some lint issues
daniel-sanche Apr 17, 2024
d5903e2
fixed mypy issues
daniel-sanche Apr 18, 2024
f9862a2
refactored system tests into class
daniel-sanche Apr 18, 2024
5cb4e82
fixed retry type
daniel-sanche Apr 18, 2024
46ef676
renamed test file
daniel-sanche Apr 18, 2024
44840f3
got system tests generated
daniel-sanche Apr 18, 2024
3c33954
fixed possible flake
daniel-sanche Apr 18, 2024
7c9c3bd
changed class order to match async
daniel-sanche Apr 18, 2024
7661fec
renamed class
daniel-sanche Apr 18, 2024
8e2db64
experiment with CrossSync annotations
daniel-sanche Apr 19, 2024
bbe5005
hacked together sync generator to work with annoptations
daniel-sanche Apr 19, 2024
4cbeaba
added sync implementations of certain functions
daniel-sanche Apr 19, 2024
86c6cd9
added crosssync to mutations batcher
daniel-sanche May 30, 2024
7b4614b
made it work with private classes
daniel-sanche May 30, 2024
d69164a
got broken unit tests working for batcher
daniel-sanche Jun 20, 2024
63fe1d7
index for replaced file names
daniel-sanche Jun 20, 2024
d40c016
simplified surface generator
daniel-sanche Jun 20, 2024
888cfc2
implemented rename_sync decorator
daniel-sanche Jun 20, 2024
6d55305
remove class decorator and abc super class
daniel-sanche Jun 20, 2024
605f874
added support for class-based replacements
daniel-sanche Jun 20, 2024
e930e54
replaced async classes
daniel-sanche Jun 20, 2024
96f92b8
added generation to ReadRowsOperation
daniel-sanche Jun 20, 2024
f37aa38
set up symbol replacement for ReadRowsOperation
daniel-sanche Jun 20, 2024
37549e9
use cross sync for retries
daniel-sanche Jun 20, 2024
b2975fb
refactored how sync implementation is handled
daniel-sanche Jun 20, 2024
77165fd
fixed imports for mutate_rows
daniel-sanche Jun 20, 2024
9b04852
fixed typing for _read_rows
daniel-sanche Jun 20, 2024
d8542f4
fixing typing issues
daniel-sanche Jun 21, 2024
975ed12
fixing mypy issues
daniel-sanche Jun 21, 2024
2dc3de4
ran blacken
daniel-sanche Jun 21, 2024
9bb7f6e
fixed executor in mutations batcher
daniel-sanche Jun 21, 2024
cc03c15
improved mutations batcher close
daniel-sanche Jun 21, 2024
c71e5a9
updated docstring
daniel-sanche Jun 21, 2024
0500969
fixed event wait
daniel-sanche Jun 21, 2024
5cd4528
added way to ignore mypy errors on generated files
daniel-sanche Jun 21, 2024
c6840b8
fixed import lint
daniel-sanche Jun 21, 2024
b52b70b
fixed mutations batcher async tests
daniel-sanche Jun 21, 2024
a476627
fixed mock path
daniel-sanche Jun 21, 2024
948d4a2
added event loop check
daniel-sanche Jun 21, 2024
c6810b6
got client unit tests passing
daniel-sanche Jun 21, 2024
f7b7523
added missing await
daniel-sanche Jun 21, 2024
d15c4a4
added typing to cross sync
daniel-sanche Jun 21, 2024
360a204
fixed type errors
daniel-sanche Jun 21, 2024
99b23e5
remove unused metaclasses
daniel-sanche Jun 21, 2024
9246589
fixed warning in tests
daniel-sanche Jun 21, 2024
9cf3923
removed old sync tests
daniel-sanche Jun 21, 2024
c59eec2
got unit tests passing
daniel-sanche Jun 21, 2024
fac2583
Merge branch 'main' into sync_generator_cross_sync
daniel-sanche Jun 22, 2024
8ef9047
updated sync files
daniel-sanche Jun 22, 2024
0705ee9
got sharding working with cross_sync
daniel-sanche Jun 22, 2024
426057f
fixed mypy errors
daniel-sanche Jun 22, 2024
0c79e39
ran blacken
daniel-sanche Jun 22, 2024
4aa53eb
generate sync unit tests
daniel-sanche Jun 24, 2024
6ae2428
improved import generation
daniel-sanche Jun 24, 2024
fdce0bc
fixed cross sync import conditional
daniel-sanche Jun 24, 2024
adc8bb7
fixed import
daniel-sanche Jun 24, 2024
31fb77a
got rpc tests passing
daniel-sanche Jun 24, 2024
fc44b30
removed custom is_async
daniel-sanche Jun 24, 2024
255e124
support dropping methods
daniel-sanche Jun 24, 2024
87aecb3
got tests passing
daniel-sanche Jun 25, 2024
a1426a5
got test_client sync tests passing
daniel-sanche Jun 25, 2024
ba351e3
dded simplified transformer to crosssync
daniel-sanche Jun 28, 2024
d6fac8e
strip out basic sync code
daniel-sanche Jun 28, 2024
d25a517
include headers
daniel-sanche Jun 28, 2024
5dd32fd
add file imports
daniel-sanche Jul 2, 2024
cd40ba9
refactoring
daniel-sanche Jul 3, 2024
fd639e4
fixed docstrings
daniel-sanche Jul 3, 2024
c1053e9
made changes to docstring format in generated files
daniel-sanche Jul 3, 2024
c925760
simplified generator visit
daniel-sanche Jul 3, 2024
9f9ec0f
replace string types
daniel-sanche Jul 3, 2024
e5168a1
add mypyy disabling
daniel-sanche Jul 3, 2024
9bd13b3
regenerated imports
daniel-sanche Jul 3, 2024
6895968
got rename_sync decorator working
daniel-sanche Jul 3, 2024
09c090d
made convert decorator
daniel-sanche Jul 3, 2024
ab28899
added CrossSync.Awaitable
daniel-sanche Jul 3, 2024
40678e0
more targeted replacements
daniel-sanche Jul 3, 2024
79f7b74
got test conversion working
daniel-sanche Jul 3, 2024
2652158
keep try import blocks
daniel-sanche Jul 3, 2024
5b31779
refactored into node transformer
daniel-sanche Jul 3, 2024
53dbb77
added pytest decorator
daniel-sanche Jul 3, 2024
e93f2ac
got test_client passing again
daniel-sanche Jul 3, 2024
515f565
added mock to crosssync
daniel-sanche Jul 3, 2024
4c6bac2
more targeted replacements
daniel-sanche Jul 3, 2024
998829e
ran blacken
daniel-sanche Jul 4, 2024
40e961e
fixed some lint issues
daniel-sanche Jul 4, 2024
ec63aa7
got tests passing
daniel-sanche Jul 4, 2024
5cdf5d9
ran black
daniel-sanche Jul 4, 2024
b964c8d
use crossync for system tests
daniel-sanche Jul 8, 2024
a968905
don't manually clear channel refresh list
daniel-sanche Jul 8, 2024
95c30f8
mark each method to convert
daniel-sanche Jul 8, 2024
8c88f08
cleaning; adding docstrings
daniel-sanche Jul 8, 2024
c93597b
use custom class for decorators
daniel-sanche Jul 9, 2024
32f1631
mark pytest methods for conversion
daniel-sanche Jul 11, 2024
b6fb1d5
convert crosssync.pytest to sync
daniel-sanche Jul 11, 2024
f90d54c
removed unneeded check
daniel-sanche Jul 11, 2024
f5dfa3e
use AstDecorator for pytest_fixture
daniel-sanche Jul 11, 2024
ce45742
renamed class decorator
daniel-sanche Jul 11, 2024
49b4808
import instead of duplicate
daniel-sanche Jul 11, 2024
18e4977
import sync classes
daniel-sanche Jul 11, 2024
48bb06f
removed sync classes
daniel-sanche Jul 11, 2024
245bd08
removed conversion decorators
daniel-sanche Jul 11, 2024
74a69c3
removed main function from cross_sync
daniel-sanche Jul 11, 2024
276add1
removed sync classes from __init__.py
daniel-sanche Jul 11, 2024
d3906bf
removed unused file
daniel-sanche Jul 11, 2024
73c6e2f
remove sync pooled generator
daniel-sanche Jul 11, 2024
1911296
reverted some style changes
daniel-sanche Jul 11, 2024
e166bbe
removed left ofer crosssync.drop
daniel-sanche Jul 11, 2024
6b244c5
removed else branches of cross sync imports
daniel-sanche Jul 11, 2024
9e1afc3
fixed mypy error
daniel-sanche Jul 11, 2024
2a46630
added back file
daniel-sanche Jul 12, 2024
2691686
removed file
daniel-sanche Jul 12, 2024
f48604e
moved non-async helper classes out of async folder
daniel-sanche Jul 12, 2024
a61c54f
fixed lint
daniel-sanche Jul 12, 2024
8b379c8
improve version string calculation
daniel-sanche Jul 12, 2024
14259e2
created method for event loop verification
daniel-sanche Jul 12, 2024
9b7c1e2
reverted some behavior
daniel-sanche Jul 12, 2024
88fda0d
added comments
daniel-sanche Jul 12, 2024
c3787ca
added comments
daniel-sanche Jul 12, 2024
7f65063
removed sync implementation from cross_sync
daniel-sanche Jul 12, 2024
caf27e2
added sync_impl
daniel-sanche Jul 12, 2024
8af6438
added cross sync ast transform system
daniel-sanche Jul 12, 2024
8d763f8
added conversion annotations
daniel-sanche Jul 12, 2024
5efc840
fixed import
daniel-sanche Jul 12, 2024
eb5cd48
refactor outputs
daniel-sanche Jul 12, 2024
e5a8792
renamed artifact class; added comments
daniel-sanche Jul 12, 2024
39ae907
added back conversion annotations
daniel-sanche Jul 12, 2024
d17a98c
Merge branch 'cross_sync_pr1_replacements' into cross_sync_pr2_genera…
daniel-sanche Jul 12, 2024
fd1fb71
fixed decorator sync_impl call
daniel-sanche Jul 12, 2024
c0b4185
Merge branch 'cross_sync_pr1_replacements' into cross_sync_pr2_genera…
daniel-sanche Jul 12, 2024
adb092e
use add_mapping in place of replace_symbols
daniel-sanche Jul 12, 2024
45efa16
support automatic attribute registration
daniel-sanche Jul 12, 2024
e1ec974
reduced replace_symbols usage in tests
daniel-sanche Jul 13, 2024
021fde2
fixed lint issues
daniel-sanche Jul 13, 2024
58405d1
Merge branch 'cross_sync_pr1_replacements' into cross_sync_pr2_genera…
daniel-sanche Jul 13, 2024
de0fd90
added missing imports
daniel-sanche Jul 13, 2024
6ca3ddd
get mappings working for sync implementation
daniel-sanche Jul 13, 2024
b2cf937
moved decorators into new file
daniel-sanche Jul 15, 2024
4860061
moved transformation from transformers into decorators
daniel-sanche Jul 16, 2024
63891d7
simplified arguments for decorators
daniel-sanche Jul 16, 2024
164f5a8
use separate decorate method
daniel-sanche Jul 16, 2024
8317973
comments and clean up
daniel-sanche Jul 17, 2024
f9dd41d
ran blacken
daniel-sanche Jul 17, 2024
22b093f
moved ast decorators into new file
daniel-sanche Jul 17, 2024
5ebf889
Merge branch 'cross_sync_pr1_replacements' into cross_sync_pr2_genera…
daniel-sanche Jul 17, 2024
8d13c5e
ran blacken
daniel-sanche Jul 17, 2024
ea8072f
Merge branch 'cross_sync_pr1_replacements' into cross_sync_pr2_genera…
daniel-sanche Jul 17, 2024
769cac1
changed sync impl name
daniel-sanche Jul 17, 2024
f87b832
fixed mapping function
daniel-sanche Jul 17, 2024
f2b6d08
convert to async with pytest mark
daniel-sanche Jul 17, 2024
754adf8
Merge branch 'cross_sync_pr1_replacements' into cross_sync_pr2_genera…
daniel-sanche Jul 17, 2024
3ed5935
convert changes async to sync def by default
daniel-sanche Jul 17, 2024
d0ba7b0
added rm_aio for stripping asyncio keywords
daniel-sanche Jul 18, 2024
37b4833
reverted client and test changes
daniel-sanche Jul 18, 2024
c63d88e
fixed lint issues
daniel-sanche Jul 22, 2024
3762a03
fixed mypy issues
daniel-sanche Jul 22, 2024
274bd36
moved cross_sync into own directory
daniel-sanche Jul 22, 2024
5611614
added docstrings
daniel-sanche Jul 22, 2024
ad95748
added README
daniel-sanche Jul 22, 2024
cad416d
fixed README formatting
daniel-sanche Jul 22, 2024
9a19658
added rm_aio to pytest and convert decorators
daniel-sanche Jul 23, 2024
02b2268
Merge branch 'main' into cross_sync2_pr1_architecture
daniel-sanche Jul 23, 2024
b64c0c7
create paths when writing sync outputs
daniel-sanche Jul 23, 2024
223f337
moved files
daniel-sanche Jul 23, 2024
3600a63
moved add_mapping into metaclass
daniel-sanche Jul 24, 2024
a36f89d
Merge branch 'main' into cross_sync2_pr1_architecture
daniel-sanche Aug 9, 2024
ebf126a
replace all instances in docstrings
daniel-sanche Aug 13, 2024
792abd9
added next to cross_sync
daniel-sanche Aug 30, 2024
18854f0
added docstring templating
daniel-sanche Sep 3, 2024
2dce3b9
added test file for cross sync
daniel-sanche Sep 3, 2024
ade18b1
added some tests
daniel-sanche Sep 4, 2024
933a626
moved wait into aliases
daniel-sanche Sep 5, 2024
8efe71d
stripped out condition_wait
daniel-sanche Sep 5, 2024
09623f4
added tests for event_wait
daniel-sanche Sep 5, 2024
6fcbc89
added tests for create_task
daniel-sanche Sep 5, 2024
9044c4a
added tests for remaining functions
daniel-sanche Sep 5, 2024
ee11e04
added test outline for decorators
daniel-sanche Sep 5, 2024
89c2abe
added tests for ExportSync
daniel-sanche Sep 5, 2024
7925b24
added tests for convert
daniel-sanche Sep 5, 2024
de32f7f
added remaining decorator tests
daniel-sanche Sep 5, 2024
3c0f1de
added mapping tests
daniel-sanche Sep 5, 2024
da38ac4
added e2e test structure for cross_sync
daniel-sanche Sep 5, 2024
169255b
fixed failing nox tests
daniel-sanche Sep 5, 2024
5eddd03
added test cases
daniel-sanche Sep 5, 2024
c616143
added tests
daniel-sanche Sep 5, 2024
042f89b
added cross_sync_methods e2e test cases
daniel-sanche Sep 6, 2024
f186d6b
added tests for class generation
daniel-sanche Sep 6, 2024
7a0c638
moved cross_sync tests into system tests
daniel-sanche Sep 6, 2024
a3cb9a6
fixed lint issues
daniel-sanche Sep 6, 2024
0c91eb7
fixed mypy
daniel-sanche Sep 6, 2024
5484f5e
changed system_emulated version
daniel-sanche Sep 6, 2024
e7881da
fixed system test version format
daniel-sanche Sep 6, 2024
bc67b30
fixed unit-3.7 issues
daniel-sanche Sep 6, 2024
11ab1d0
fixed lint
daniel-sanche Sep 6, 2024
13abfd4
implemented wait manually
daniel-sanche Sep 9, 2024
7dc9a2b
simplified file processing
daniel-sanche Sep 11, 2024
41576f7
fixed issues in generation
daniel-sanche Sep 11, 2024
ef00397
fixed string access
daniel-sanche Sep 11, 2024
ea571bd
simplified transformers. Removed CrossSyncMethodHandler
daniel-sanche Sep 12, 2024
e42655b
simplified Convert decorator
daniel-sanche Sep 12, 2024
e972385
fixed 3.7 tests
daniel-sanche Sep 12, 2024
81a06f8
fixed mypy issues
daniel-sanche Sep 12, 2024
db8c156
extract header from code
daniel-sanche Sep 12, 2024
37c3226
add warning to generated header
daniel-sanche Sep 13, 2024
54ee3be
updated README
daniel-sanche Sep 13, 2024
d44b829
made drop_method into drop, with support for classes
daniel-sanche Sep 13, 2024
61490e5
renamed export into convert_class
daniel-sanche Sep 13, 2024
a45a6f6
extracted branch trimming into own transformer
daniel-sanche Sep 13, 2024
dd2a65f
fixed visit to generic visit
daniel-sanche Sep 13, 2024
59a5df2
update transformer value access
daniel-sanche Sep 17, 2024
77560c9
moved cross_sync directory
daniel-sanche Sep 18, 2024
252ddef
fixed outdated name
daniel-sanche Sep 18, 2024
720cf81
fixed import
daniel-sanche Sep 18, 2024
c82d967
moved tests
daniel-sanche Sep 18, 2024
48d44a6
renamed test file
daniel-sanche Sep 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .cross_sync/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# CrossSync

CrossSync provides a simple way to share logic between async and sync code.
It is made up of a small library that provides:
1. a set of shims that provide a shared sync/async API surface
2. annotations that are used to guide generation of a sync version from an async class

Using CrossSync, the async code is treated as the source of truth, and sync code is generated from it.

## Usage

### CrossSync Shims

Many Asyncio components have direct, 1:1 threaded counterparts for use in non-asyncio code. CrossSync
provides a compatibility layer that works with both

| CrossSync | Asyncio Version | Sync Version |
| --- | --- | --- |
| CrossSync.Queue | asyncio.Queue | queue.Queue |
| CrossSync.Condition | asyncio.Condition | threading.Condition |
| CrossSync.Future | asyncio.Future | Concurrent.futures.Future |
| CrossSync.Task | asyncio.Task | Concurrent.futures.Future |
| CrossSync.Event | asyncio.Event | threading.Event |
| CrossSync.Semaphore | asyncio.Semaphore | threading.Semaphore |
| CrossSync.Awaitable | typing.Awaitable | typing.Union (no-op type) |
| CrossSync.Iterable | typing.AsyncIterable | typing.Iterable |
| CrossSync.Iterator | typing.AsyncIterator | typing.Iterator |
| CrossSync.Generator | typing.AsyncGenerator | typing.Generator |
| CrossSync.Retry | google.api_core.retry.AsyncRetry | google.api_core.retry.Retry |
| CrossSync.StopIteration | StopAsyncIteration | StopIteration |
| CrossSync.Mock | unittest.mock.AsyncMock | unittest.mock.Mock |

Custom aliases can be added using `CrossSync.add_mapping(class, name)`

Additionally, CrossSync provides method implementations that work equivalently in async and sync code:
- `CrossSync.sleep()`
- `CrossSync.gather_partials()`
- `CrossSync.wait()`
- `CrossSync.condition_wait()`
- `CrossSync,event_wait()`
- `CrossSync.create_task()`
- `CrossSync.retry_target()`
- `CrossSync.retry_target_stream()`

### Annotations

CrossSync provides a set of annotations to mark up async classes, to guide the generation of sync code.

- `@CrossSync.convert_sync`
- marks classes for conversion. Unmarked classes will be copied as-is
- if add_mapping is included, the async and sync classes can be accessed using a shared CrossSync.X alias
- `@CrossSync.convert`
- marks async functions for conversion. Unmarked methods will be copied as-is
- `@CrossSync.drop`
- marks functions or classes that should not be included in sync output
- `@CrossSync.pytest`
- marks test functions. Test functions automatically have all async keywords stripped (i.e., rm_aio is unneeded)
- `CrossSync.add_mapping`
- manually registers a new CrossSync.X alias, for custom types
- `CrossSync.rm_aio`
- Marks regions of the code that include asyncio keywords that should be stripped during generation

### Code Generation

Generation can be initiated using `python .cross_sync/generate.py .`
from the root of the project. This will find all classes with the `__CROSS_SYNC_OUTPUT__ = "path/to/output"`
annotation, and generate a sync version of classes marked with `@CrossSync.convert_sync` at the output path.

## Architecture

CrossSync is made up of two parts:
- the runtime shims and annotations live in `/google/cloud/bigtable/_cross_sync`
- the code generation logic lives in `/.cross_sync/` in the repo root
107 changes: 107 additions & 0 deletions .cross_sync/generate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import annotations
from typing import Sequence
import ast
"""
Entrypoint for initiating an async -> sync conversion using CrossSync

Finds all python files rooted in a given directory, and uses
transformers.CrossSyncFileProcessor to handle any files marked with
__CROSS_SYNC_OUTPUT__
"""


def extract_header_comments(file_path) -> str:
"""
Extract the file header. Header is defined as the top-level
comments before any code or imports
"""
header = []
with open(file_path, "r") as f:
for line in f:
if line.startswith("#") or line.strip() == "":
header.append(line)
else:
break
header.append("\n# This file is automatically generated by CrossSync. Do not edit manually.\n\n")
return "".join(header)


class CrossSyncOutputFile:

def __init__(self, output_path: str, ast_tree, header: str | None = None):
self.output_path = output_path
self.tree = ast_tree
self.header = header or ""

def render(self, with_black=True, save_to_disk: bool = False) -> str:
"""
Render the file to a string, and optionally save to disk

Args:
with_black: whether to run the output through black before returning
save_to_disk: whether to write the output to the file path
"""
full_str = self.header + ast.unparse(self.tree)
if with_black:
import black # type: ignore
import autoflake # type: ignore

full_str = black.format_str(
autoflake.fix_code(full_str, remove_all_unused_imports=True),
mode=black.FileMode(),
)
if save_to_disk:
import os
os.makedirs(os.path.dirname(self.output_path), exist_ok=True)
with open(self.output_path, "w") as f:
f.write(full_str)
return full_str


def convert_files_in_dir(directory: str) -> set[CrossSyncOutputFile]:
import glob
from transformers import CrossSyncFileProcessor

# find all python files in the directory
files = glob.glob(directory + "/**/*.py", recursive=True)
# keep track of the output files pointed to by the annotated classes
artifacts: set[CrossSyncOutputFile] = set()
file_transformer = CrossSyncFileProcessor()
# run each file through ast transformation to find all annotated classes
for file_path in files:
ast_tree = ast.parse(open(file_path).read())
output_path = file_transformer.get_output_path(ast_tree)
if output_path is not None:
# contains __CROSS_SYNC_OUTPUT__ annotation
converted_tree = file_transformer.visit(ast_tree)
header = extract_header_comments(file_path)
artifacts.add(CrossSyncOutputFile(output_path, converted_tree, header))
# return set of output artifacts
return artifacts


def save_artifacts(artifacts: Sequence[CrossSyncOutputFile]):
for a in artifacts:
a.render(save_to_disk=True)


if __name__ == "__main__":
import sys

search_root = sys.argv[1]
outputs = convert_files_in_dir(search_root)
print(f"Generated {len(outputs)} artifacts: {[a.output_path for a in outputs]}")
save_artifacts(outputs)
Loading
Loading