Skip to content

Commit 7bff028

Browse files
authored
feat: partial @streaming blob support for Python (#747)
Adds partial support for the `@streaming` Smithy trait on blobs, depending on a `actions-and-streaming-stdlibs` branch of Dafny that adds an Actions standard library, and only implemented when targeting Python so far. Event streaming is not technically supported yet because more codegen changes are necessary, but this will be a relatively small delta, as the Dafny types involved are already handled. The motivation behind merging this incomplete work is largely to get the test model coverage into CI, so that it doesn't regress as the feature is completed, especially when Dafny verification is perturbed in future versions. The next priority will be to complete the Dafny branch and merge it to Dafny mainline. Note that `smithy-dafny` will still emit a `DANGER` validation event saying that `@streaming` is not supported, which is intentional in order to guard against using the feature in production before it is fully completed: the test models exercising it explicitly suppress this event. * Added a `dafny` submodule under `TestModels/dafny-dependencies/dafny` tracking the `actions-and-streaming-stdlibs` branch, just to access the contents of `Source/DafnyStandardLibraries/src/Std/Actions` etc. This copy of Dafny is never built or used for any other building tasks. * Added a build task under `StandardLibrary` to build a .doo file from a subset of the Dafny standard library files above (using `DafnyStandardLibraries-smithy-dafny-subset.toml`). This is then used as a `--library` argument when verifying/translating polymorph libraries. This approach allows the standard library source to be built with different but compatible options such as `--reads-clauses-on-methods`. * This is guarded by a `USE_DAFNY_STANDARD_LIBRARIES` Makefile variable, since a newer Dafny is required for this to work. * Bumped the high watermark Dafny version tested in CI to 4.9.1, which is necessary since the standard library above uses newer features like `@`-attributes. * Modified Dafny and Python codegen to emit references to the `ByteStream` and `RewindableByteStream` types, and removed the previous workaround to first `.read()` all data in Python. * Because streams have mutable state, the Dafny code generation needs to take them into account when generating things like `modifies` clauses. I haven't yet implemented this, instead using a patch file to add the missing specification to the `Streaming` test model code. * Modified the `aws-sdk/s3` test model and fleshed the `Streaming` test model out to actually test the feature. * Removes not-grep, since our globs are actually completely broken and the tool doesn't support our current code layout, and it was complaining about the contents of the `dafny` submodule. See #763. Reviewer note: it is worth reading the contents of the pending [Actions](https://github.com/dafny-lang/dafny/tree/actions-and-streaming-stdlibs/Source/DafnyStandardLibraries/src/Std/Actions) and [Streams](https://github.com/dafny-lang/dafny/tree/actions-and-streaming-stdlibs/Source/DafnyStandardLibraries/src/Std/Streams) Dafny libraries, but they are still under construction and I'm not claiming they will not change before being merged. Interface feedback is welcome but is not intended to be a hard requirement in scope for this review.
1 parent 2f5fabd commit 7bff028

File tree

45 files changed

+1199
-93
lines changed

Some content is hidden

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

45 files changed

+1199
-93
lines changed

.github/not-grep.toml

-30
This file was deleted.

.github/workflows/pull.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ jobs:
1010
steps:
1111
- name: Populate Dafny versions list
1212
id: populate-dafny-versions-list
13-
run: echo "dafny-versions-list=['4.5.0','4.8.0']" >> $GITHUB_OUTPUT
13+
run: echo "dafny-versions-list=['4.7.0','4.9.1']" >> $GITHUB_OUTPUT
1414
- name: Populate Dafny versions list for "only new versions" languages (Python)
1515
id: populate-only-new-dafny-versions-list
16-
run: echo "only-new-dafny-versions-list=['4.8.0']" >> $GITHUB_OUTPUT
16+
run: echo "only-new-dafny-versions-list=['4.9.1']" >> $GITHUB_OUTPUT
1717
outputs:
1818
dafny-version-list: ${{ steps.populate-dafny-versions-list.outputs.dafny-versions-list }}
1919
only-new-dafny-version-list: ${{ steps.populate-only-new-dafny-versions-list.outputs.only-new-dafny-versions-list }}

.github/workflows/push.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ jobs:
1212
steps:
1313
- name: Populate Dafny versions list
1414
id: populate-dafny-versions-list
15-
run: echo "dafny-versions-list=['4.5.0','4.8.0']" >> $GITHUB_OUTPUT
15+
run: echo "dafny-versions-list=['4.5.0','4.9.1']" >> $GITHUB_OUTPUT
1616
- name: Populate Dafny versions list for "only new versions" languages (Python, Go)
1717
id: populate-only-new-dafny-versions-list
18-
run: echo "only-new-dafny-versions-list=['4.8.0']" >> $GITHUB_OUTPUT
18+
run: echo "only-new-dafny-versions-list=['4.9.1']" >> $GITHUB_OUTPUT
1919
outputs:
2020
dafny-version-list: ${{ steps.populate-dafny-versions-list.outputs.dafny-versions-list }}
2121
only-new-dafny-version-list: ${{ steps.populate-only-new-dafny-versions-list.outputs.only-new-dafny-versions-list }}

.github/workflows/smithy-polymorph.yml

+2-4
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ jobs:
1717
- uses: actions/checkout@v3
1818
with:
1919
submodules: recursive
20+
2021
- uses: actions/setup-java@v3
2122
with:
2223
distribution: "corretto"
2324
java-version: "17"
25+
2426
- name: Setup Dafny
2527
uses: dafny-lang/setup-dafny-action@v1.7.0
2628
with:
@@ -45,7 +47,3 @@ jobs:
4547
shell: bash
4648
working-directory: TestModels/SimpleTypes/SimpleString
4749
run: make polymorph_dafny
48-
49-
- name: not-grep
50-
if: matrix.os == 'ubuntu-22.04'
51-
uses: mattsb42-meta/not-grep@1.0.0

.gitmodules

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
[submodule "smithy-dafny-codegen-modules/smithy-rs"]
22
path = smithy-dafny-codegen-modules/smithy-rs
33
url = https://github.com/smithy-lang/smithy-rs.git
4+
[submodule "TestModels/dafny-dependencies/dafny"]
5+
path = TestModels/dafny-dependencies/dafny
6+
url = git@github.com:dafny-lang/dafny.git
7+
branch = actions-and-streaming-stdlibs

SmithyDafnyMakefile.mk

+8-2
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ verify:
9595
--log-format csv \
9696
--verification-time-limit $(VERIFY_TIMEOUT) \
9797
--resource-limit $(MAX_RESOURCE_COUNT) \
98+
$(if $(USE_DAFNY_STANDARD_LIBRARIES), --library:$(PROJECT_ROOT)/$(STD_LIBRARY)/bin/DafnyStandardLibraries-smithy-dafny-subset.doo, ) \
9899
$(DAFNY_OPTIONS) \
99100
%
100101

@@ -110,6 +111,7 @@ verify_single:
110111
--log-format text \
111112
--verification-time-limit $(VERIFY_TIMEOUT) \
112113
--resource-limit $(MAX_RESOURCE_COUNT) \
114+
$(if $(USE_DAFNY_STANDARD_LIBRARIES), --library:$(PROJECT_ROOT)/$(STD_LIBRARY)/bin/DafnyStandardLibraries-smithy-dafny-subset.doo, ) \
113115
$(DAFNY_OPTIONS) \
114116
$(if ${PROC},-proc:*$(PROC)*,) \
115117
$(FILE)
@@ -207,6 +209,7 @@ transpile_implementation:
207209
$(DAFNY_OTHER_FILES) \
208210
$(TRANSPILE_MODULE_NAME) \
209211
$(if $(strip $(STD_LIBRARY)) , --library:$(PROJECT_ROOT)/$(STD_LIBRARY)/src/Index.dfy, ) \
212+
$(if $(USE_DAFNY_STANDARD_LIBRARIES) , --library:$(PROJECT_ROOT)/$(STD_LIBRARY)/bin/DafnyStandardLibraries-smithy-dafny-subset.doo, ) \
210213
$(TRANSLATION_RECORD) \
211214
$(TRANSPILE_DEPENDENCIES)
212215

@@ -245,6 +248,7 @@ transpile_test:
245248
$(DAFNY_OPTIONS) \
246249
$(DAFNY_OTHER_FILES) \
247250
$(if $(strip $(STD_LIBRARY)) , --library:$(PROJECT_ROOT)/$(STD_LIBRARY)/src/Index.dfy, ) \
251+
$(if $(USE_DAFNY_STANDARD_LIBRARIES) , --library:$(PROJECT_ROOT)/$(STD_LIBRARY)/bin/DafnyStandardLibraries-smithy-dafny-subset.doo, ) \
248252
$(TRANSLATION_RECORD) \
249253
$(SOURCE_TRANSLATION_RECORD) \
250254
$(TRANSPILE_MODULE_NAME) \
@@ -253,7 +257,7 @@ transpile_test:
253257
# If we are not the StandardLibrary, transpile the StandardLibrary.
254258
# Transpile all other dependencies
255259
transpile_dependencies:
256-
$(if $(strip $(STD_LIBRARY)), $(MAKE) -C $(PROJECT_ROOT)/$(STD_LIBRARY) transpile_implementation_$(LANG), )
260+
$(if $(strip $(STD_LIBRARY)), $(MAKE) -C $(PROJECT_ROOT)/$(STD_LIBRARY) transpile_implementation_$(LANG) USE_DAFNY_STANDARD_LIBRARIES=$(USE_DAFNY_STANDARD_LIBRARIES), )
257261
$(patsubst %, $(MAKE) -C $(PROJECT_ROOT)/% transpile_implementation_$(LANG);, $(PROJECT_DEPENDENCIES))
258262

259263
transpile_dependencies_test:
@@ -326,7 +330,7 @@ _polymorph_wrapped:
326330
$(POLYMORPH_OPTIONS)";
327331

328332
_polymorph_dependencies:
329-
$(if $(strip $(STD_LIBRARY)), $(MAKE) -C $(PROJECT_ROOT)/$(STD_LIBRARY) polymorph_$(POLYMORPH_LANGUAGE_TARGET) LIBRARY_ROOT=$(PROJECT_ROOT)/$(STD_LIBRARY), )
333+
$(if $(strip $(STD_LIBRARY)), $(MAKE) -C $(PROJECT_ROOT)/$(STD_LIBRARY) polymorph_$(POLYMORPH_LANGUAGE_TARGET) LIBRARY_ROOT=$(PROJECT_ROOT)/$(STD_LIBRARY) USE_DAFNY_STANDARD_LIBRARIES=$(USE_DAFNY_STANDARD_LIBRARIES), )
330334
@$(foreach dependency, \
331335
$(PROJECT_DEPENDENCIES), \
332336
$(MAKE) -C $(PROJECT_ROOT)/$(dependency) polymorph_$(POLYMORPH_LANGUAGE_TARGET); \
@@ -695,6 +699,8 @@ test_go:
695699

696700
########################## Python targets
697701

702+
python: polymorph_dafny transpile_python polymorph_python test_python
703+
698704
# Install packages via `python3 -m pip`,
699705
# which is the syntax Smithy-Python and Smithy-Dafny Python use
700706
# to invoke these packages.

TestModels/Streaming/Makefile

+26
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
CORES=2
55

6+
USE_DAFNY_STANDARD_LIBRARIES=1
7+
8+
ENABLE_EXTERN_PROCESSING=1
9+
610
include ../SharedMakefile.mk
711

812
NAMESPACE=simple.streaming
@@ -18,4 +22,26 @@ SMITHY_DEPS=dafny-dependencies/Model/traits.smithy
1822

1923
# This project has no dependencies
2024
# DEPENDENT-MODELS:=
25+
26+
# Python
27+
28+
PYTHON_MODULE_NAME=simple_streaming
29+
30+
TRANSLATION_RECORD_PYTHON := \
31+
--translation-record ../dafny-dependencies/StandardLibrary/runtimes/python/src/smithy_dafny_standard_library/internaldafny/generated/dafny_src-py.dtr
32+
2133
# LIBRARIES :=
34+
35+
# Constants for languages that drop extern names (Python, Go)
36+
37+
TYPES_FILE_PATH=Model/SimpleStreamingTypes.dfy
38+
TYPES_FILE_WITH_EXTERN_STRING="module {:extern \"simple.streaming.internaldafny.types\" } SimpleStreamingTypes"
39+
TYPES_FILE_WITHOUT_EXTERN_STRING="module SimpleStreamingTypes"
40+
41+
INDEX_FILE_PATH=src/Index.dfy
42+
INDEX_FILE_WITH_EXTERN_STRING="module {:extern \"simple.streaming.internaldafny\"} SimpleStreaming refines AbstractSimpleStreamingService"
43+
INDEX_FILE_WITHOUT_EXTERN_STRING="module SimpleStreaming refines AbstractSimpleStreamingService"
44+
45+
WRAPPED_INDEX_FILE_PATH=src/WrappedSimpleStreamingImpl.dfy
46+
WRAPPED_INDEX_FILE_WITH_EXTERN_STRING="module {:extern \"simple.streaming.internaldafny.wrapped\"} WrappedSimpleStreamingService refines WrappedAbstractSimpleStreamingService"
47+
WRAPPED_INDEX_FILE_WITHOUT_EXTERN_STRING="module WrappedSimpleStreamingService refines WrappedAbstractSimpleStreamingService"

0 commit comments

Comments
 (0)