Skip to content

Commit

Permalink
a little bit more setup. Make distinction between ast builder API, pr…
Browse files Browse the repository at this point in the history
…ocedural API, and add a verify function
  • Loading branch information
FedericoAureliano committed Feb 10, 2024
1 parent 6c999ef commit fd148ba
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 3 deletions.
20 changes: 18 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,29 @@ UCLID5 Python API
The official repository for the UCLID5 Python API.


Installation
============
To install the UCLID5 Python API, you can use pip::

pip install . # from the root directory of the project

This will install the `uclid` package and its dependencies.

Usage
=====
See tests for examples of how to use the API.


Making Changes & Contributing
=============================

See `CONTRIBUTING.rst` for more information on how to contribute to this project.

Note that this project uses `pre-commit`, please make sure to install it before making any
changes::
To run all tests and get a covereage report, just execute `tox` in the root
directory of the project.

Note that this project uses `pre-commit`, please make sure to install it before
making any changes::

pip install pre-commit
cd uclid-api
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ package_dir =
# For more information, check out https://semver.org/.
install_requires =
importlib-metadata; python_version<"3.8"
wget


[options.packages.find]
Expand Down
3 changes: 3 additions & 0 deletions src/uclid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@
__version__ = "unknown"
finally:
del version, PackageNotFoundError

from .procedural import Module # noqa: F401
from .run import verify # noqa: F401
File renamed without changes.
9 changes: 9 additions & 0 deletions src/uclid/procedural.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from uclid.builder import UclidModule


class Module:
def __init__(self, name):
self.module = UclidModule(name)

def __str__(self):
return self.module.__inject__()
75 changes: 75 additions & 0 deletions src/uclid/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import logging
import os
import pathlib
import shutil
import subprocess
import tempfile
import zipfile

import wget

__author__ = "Federico Mora"
__copyright__ = "Federico Mora"
__license__ = "MIT"

_logger = logging.getLogger(__name__)

LATEST_RELEASE_URL = "https://github.com/uclid-org/uclid/releases/download/v0.9.5d-prerelease/uclid-0.9.5.zip" # noqa: E501


def verify(query: str):
uclid = download_uclid()
with tempfile.NamedTemporaryFile() as tmp:
tmp.write(query.encode())
tmp.flush()
output = subprocess.run([uclid, tmp.name], capture_output=True)
return output.stdout.decode("utf-8")


def download_uclid():
# Get the directory of this file
base = pathlib.Path(__file__).parent.resolve()
_logger.info(f"Base directory: {base}")

# Get the other directories we'll use
build = os.path.join(base, "build")
uclid = os.path.join(build, "uclid-0.9.5", "bin", "uclid")

# if uclid exists, return it
if os.path.exists(uclid):
_logger.info("Uclid exists")
return uclid

# delete build directory if it exists
_logger.info("Deleting build directory if it exists")
if os.path.exists(build):
shutil.rmtree(build)
_logger.info("Build directory deleted")

# make a build directory if it doesn't exist
_logger.info("Making build directory")
os.makedirs(build)

# download uclid
_logger.info("Downloading Uclid")
wget.download(LATEST_RELEASE_URL, os.path.join(build, "uclid.zip"))
_logger.info("Uclid downloaded")

# unzip uclid.zip
_logger.info("Unzipping Uclid")
with zipfile.ZipFile(os.path.join(build, "uclid.zip"), "r") as zip_ref:
zip_ref.extractall(build)
_logger.info("Uclid unzipped")

# if on windows, add .bat to uclid
if os.name == "nt":
uclid += ".bat"

_logger.info(f"Uclid executable: {uclid}")

# make uclid executable
_logger.info("Making Uclid executable")
os.chmod(uclid, 0o755)
_logger.info("Uclid is now executable")

return uclid
2 changes: 1 addition & 1 deletion tests/test_ast.py → tests/test_builder.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from uclid.ast import Uadd
from uclid.builder import Uadd

__author__ = "Federico Mora"
__copyright__ = "Federico Mora"
Expand Down
11 changes: 11 additions & 0 deletions tests/test_procedural.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
__author__ = "Federico Mora"
__copyright__ = "Federico Mora"
__license__ = "MIT"


def test_empty_module():
from uclid import Module

m = Module("empty")
# assert str(m).split() == "module empty { }".split()
assert "module empty {" in str(m)
23 changes: 23 additions & 0 deletions tests/test_run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import subprocess

from uclid import verify
from uclid.run import download_uclid

__author__ = "Federico Mora"
__copyright__ = "Federico Mora"
__license__ = "MIT"


def test_download():
uclid = download_uclid()
output = subprocess.run([uclid, "--help"], capture_output=True)
assert output.returncode == 0
output = output.stdout.decode("utf-8")
assert "uclid 0.9.5" in output, f"uclid version not found in {output}"


def test_run():
query = "module main { }"
output = verify(query).split()
expected = "Successfully parsed 1 and instantiated 1 module(s).".split()
assert output == expected, f"Expected `{expected}` but got `{output}`"

0 comments on commit fd148ba

Please sign in to comment.