Skip to content

Commit

Permalink
Merge pull request #149 from BerkeleyLearnVerify/3.x
Browse files Browse the repository at this point in the history
Scenic 3 public release
  • Loading branch information
dfremont authored Jun 30, 2023
2 parents ee56a11 + 88dcce5 commit d238320
Show file tree
Hide file tree
Showing 501 changed files with 48,623 additions and 31,376 deletions.
3 changes: 3 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# .git-blame-ignore-revs
# Ran isort and black on the whole codebase
360c67fab09d172498b3014510ee3658643d12da
19 changes: 19 additions & 0 deletions .github/workflows/check-formatting.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: format

on:
push:
pull_request:
workflow_call:

jobs:
check:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Run black to check formatting
uses: psf/black@stable

- name: Run isort to check import order
uses: isort/isort-action@v1
43 changes: 41 additions & 2 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,73 @@ on:
type: string

jobs:
build:
check-format:
uses: ./.github/workflows/check-formatting.yml

test:
strategy:
fail-fast: true
matrix:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
python-version: ["3.8", "3.9", "3.10", "3.11"]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}

steps:
- name: Checkout given ref
uses: actions/checkout@v3
if: inputs.ref != ''
with:
ref: ${{ inputs.ref }}

- name: Checkout current branch
uses: actions/checkout@v3
if: inputs.ref == ''
with:
ref: ${{ github.ref }}

- name: Install non-Python dependencies (Linux)
if: ${{ matrix.os == 'ubuntu-latest' }}
uses: awalsh128/cache-apt-pkgs-action@latest
with:
packages: blender openscad

- name: Restore cached non-Python dependencies (Windows)
id: windows-cache-deps
if: ${{ matrix.os == 'windows-latest' }}
uses: actions/cache@v3
with:
path: downloads
key: windows-deps

- name: Download non-Python dependencies (Windows)
if: ${{ matrix.os == 'windows-latest' && steps.windows-cache-deps.outputs.cache-hit != 'true' }}
run: |
New-Item -Path downloads -ItemType Directory -Force
Invoke-WebRequest https://files.openscad.org/OpenSCAD-2021.01-x86-64.zip -O downloads/openscad.zip
Invoke-WebRequest https://download.blender.org/release/Blender3.6/blender-3.6.0-windows-x64.zip -O downloads/blender.zip
- name: Install non-Python dependencies (Windows)
if: ${{ matrix.os == 'windows-latest' }}
run: |
Expand-Archive -Path downloads/openscad.zip -DestinationPath openscad
Move-Item -Path openscad/openscad-2021.01 -Destination $Env:Programfiles\OpenSCAD
Expand-Archive -Path downloads/blender.zip -DestinationPath blender
Move-Item -Path blender/blender-3.6.0-windows-x64 -Destination "$Env:Programfiles\Blender Foundation\Blender"
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'

- name: Update pip
run: |
python -m pip install --upgrade pip
- name: Install Scenic and dependencies
run: |
python -m pip install -e ".[test]"
- name: Run pytest
run: |
pytest ${{ inputs.options || '--no-graphics' }}
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,11 @@ celerybeat-schedule
.env
.venv
env/
venv/
venv*/
ENV/
env.bak/
venv.bak/
scenic.venv/

# Spyder project settings
.spyderproject
Expand All @@ -131,3 +132,6 @@ venv.bak/
dmypy.json

*.cproject

# generated parser
src/scenic/syntax/parser.py
11 changes: 11 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
repos:
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
language_version: python3.11

- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
16 changes: 16 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
GRAMMAR = ./src/scenic/syntax/scenic.gram
PARSER = ./src/scenic/syntax/parser.py

.PHONY: all
all: $(PARSER)

$(PARSER): $(GRAMMAR)
python -m pegen $(GRAMMAR) -o $(PARSER)

format:
isort .
black .

.PHONY: clean
clean:
-rm $(PARSER)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file added assets/meshes/bmwx5_hull.obj.bz2
Binary file not shown.
Binary file added assets/meshes/chair.obj.bz2
Binary file not shown.
Binary file added assets/meshes/classic_plane.obj.bz2
Binary file not shown.
Binary file added assets/meshes/coffee_table.obj.bz2
Binary file not shown.
Binary file added assets/meshes/couch.obj.bz2
Binary file not shown.
Binary file added assets/meshes/dining_chair.obj.bz2
Binary file not shown.
Binary file added assets/meshes/dining_table.obj.bz2
Binary file not shown.
Binary file added assets/meshes/webots_rock_large.obj.bz2
Binary file not shown.
Binary file added assets/meshes/webots_rock_small.obj.bz2
Binary file not shown.
26 changes: 26 additions & 0 deletions docs/_templates/autosummary/module.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
{% for item in modules|sort %}
{{item.rpartition('.')[2]}}
{%- endfor %}

.. comment to get Sphinx to recognize end of autosummary directive
{% endif %}
{% endblock %}

Expand Down Expand Up @@ -45,6 +47,18 @@
{% endif %}
{% endblock %}

{% block behaviors %}
{% if behaviors %}
.. rubric:: Behaviors

.. autosummary::
:nosignatures:
{% for item in behaviors %}
{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

{% block classes %}
{% if classes %}
.. rubric:: Classes
Expand All @@ -69,6 +83,18 @@
{% endif %}
{% endblock %}

{% block scenarios %}
{% if scenarios %}
.. rubric:: Scenarios

.. autosummary::
:nosignatures:
{% for item in scenarios %}
{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

Member Details
==============
{% endif %}
55 changes: 55 additions & 0 deletions docs/_templates/installation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
Next, activate the `virtual environment <https://docs.python.org/3/tutorial/venv.html>`_ in which you want to install Scenic.
To create and activate a new virtual environment called :file:`venv`, you can run the following commands:

.. venv-setup-start
.. code-block:: text
python3 -m venv venv
source venv/bin/activate
.. venv-setup-end
Once your virtual environment is activated, you no longer need to use a name like ``python3`` or ``python3.11``; use just :command:`python` to ensure you're running the copy of Python in your virtual environment.

Next, make sure your :command:`pip` tool is up-to-date:

.. code-block:: text
python -m pip install --upgrade pip
Now you can install Scenic either from the repository or from PyPI:

.. tabs::

.. tab:: Repository

The following commands will clone the `Scenic repository <https://github.com/BerkeleyLearnVerify/Scenic>`_ into a folder called :file:`Scenic` and install Scenic from there.
It is an "editable install", so if you later update the repository with :command:`git pull` or make changes to the code yourself, you won't need to reinstall Scenic.

.. code-block:: text
git clone https://github.com/BerkeleyLearnVerify/Scenic
cd Scenic
python -m pip install -e .
If you will be developing Scenic, you will want to use a variant of the last command to install additional development dependencies: see :doc:`developing`.

.. tab:: PyPI

The following command will install the latest full release of Scenic from `PyPI <https://pypi.org/project/scenic/>`_:

.. code-block:: text
python -m pip install scenic
Note that this command skips experimental alpha and beta releases, preferring stable versions.
If you want to get the very latest version available on PyPI (which may still be behind the repository), run:

.. code-block:: text
python -m pip install --pre scenic
You can also install specific versions with a command like:

.. code-block:: text
python -m pip install scenic==2.0.0
93 changes: 93 additions & 0 deletions docs/analyzer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"""Version of sphinx.pycode.ModuleAnalyzer supporting Scenic modules.
This code is mostly copied from ModuleAnalyzer and its helper classes,
with minor changes.
"""

from collections import OrderedDict
from token import DEDENT, INDENT, NAME, NEWLINE, NUMBER, OP, STRING
from tokenize import COMMENT, NL

from sphinx.errors import PycodeError
from sphinx.pycode import ModuleAnalyzer
from sphinx.pycode.parser import DefinitionFinder, Parser, VariableCommentPicker

from scenic.syntax.parser import parse_string


class ScenicModuleAnalyzer(ModuleAnalyzer):
def analyze(self):
if self._analyzed:
return
if not self.srcname.endswith((".scenic", ".sc")):
super().analyze()
return

try:
parser = ScenicParser(self.code)
parser.parse()

self.attr_docs = OrderedDict()
for scope, comment in parser.comments.items():
if comment:
self.attr_docs[scope] = comment.splitlines() + [""]
else:
self.attr_docs[scope] = [""]

self.annotations = parser.annotations
self.finals = parser.finals
self.overloads = parser.overloads
self.tags = parser.definitions
self.tagorder = parser.deforders
self._analyzed = True
except Exception as exc:
raise PycodeError("parsing %r failed: %r" % (self.srcname, exc)) from exc


class ScenicDefinitionFinder(DefinitionFinder):
def parse(self):
"""Parse the code to obtain location of definitions."""
while True:
token = self.fetch_token()
if token is None:
break
elif token == COMMENT:
pass
elif token == [OP, "@"] and (
self.previous is None or self.previous.match(NEWLINE, NL, INDENT, DEDENT)
):
if self.decorator is None:
self.decorator = token
elif token.match([NAME, "class"]):
self.parse_definition("class")
elif token.match([NAME, "def"]):
self.parse_definition("def")
elif token.match([NAME, "behavior"]):
self.parse_definition("behavior")
elif token.match([NAME, "monitor"]):
self.parse_definition("monitor")
elif token.match([NAME, "scenario"]):
self.parse_definition("scenario")
elif token == INDENT:
self.indents.append(("other", None, None))
elif token == DEDENT:
self.finalize_block()


class ScenicParser(Parser):
def parse_comments(self):
"""Parse the code and pick up comments."""
tree = parse_string(self.code, "exec")
picker = VariableCommentPicker(self.code.splitlines(True), self.encoding)
picker.visit(tree)
self.annotations = picker.annotations
self.comments = picker.comments
self.deforders = picker.deforders
self.finals = picker.finals
self.overloads = picker.overloads

def parse_definition(self) -> None:
"""Parse the location of definitions from the code."""
parser = ScenicDefinitionFinder(self.code.splitlines(True))
parser.parse()
self.definitions = parser.definitions
Loading

0 comments on commit d238320

Please sign in to comment.