Skip to content
This repository was archived by the owner on Mar 8, 2020. It is now read-only.

Python client v3 (UASTv2) #128

Merged
merged 53 commits into from
Mar 12, 2019
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
9b5b502
use the new libuast; rewrite bindings using cpp layer of libuast
Oct 4, 2018
2788a1a
working bindings prototype
Oct 11, 2018
8e39632
fix string memory management
Oct 16, 2018
d3b6bf9
refactoring: NodeExtType->PyNodeExtType for consistency
bzz Oct 16, 2018
6ce2b11
refactoring: NodeExt->PyNodeExt for consistency
bzz Oct 16, 2018
7bac87f
refactoring: PyUastType->PyContextType for consistency
bzz Oct 16, 2018
8b84e4a
refactoring: PyUast->PyContext for consistency
bzz Oct 16, 2018
1fa1d0d
refactoring: fix comments + fmt after rebase
bzz Oct 17, 2018
9e88733
apply review feedback
bzz Oct 17, 2018
98b3ef8
fix replace
Oct 17, 2018
96abf64
Build fixes, comment out v1 things, some other adjustements
Oct 18, 2018
151e61c
Recover grpc sdk v1 protocol for some grpc objects
Oct 22, 2018
7f583ea
Forward port the aliases refactor by Vadim
Oct 22, 2018
6ba57fc
Forward port travis changes
Oct 24, 2018
24fd7b6
Merge branch 'master' into v3
juanjux Oct 24, 2018
a2ca471
fix pip install
Oct 30, 2018
e308038
update the client to use both protocols
Oct 30, 2018
0d675e1
Remove unused and broken import
Oct 31, 2018
91b798b
Compile the ext module from an static libuast object
Oct 31, 2018
acec219
enable building the client with static libuast
Nov 1, 2018
2fd570c
do not free the query string in filter, it seems to be borrowed
Nov 1, 2018
d05770c
improve the native Python wrappers and update the readme
Nov 1, 2018
272acc9
fix error handling in native extension
Nov 2, 2018
270445b
Explicit cast to char* to avoid nasty warning with latest G++
Nov 8, 2018
1f977e4
PEP8
Nov 8, 2018
20890e0
Renamed PyContext to PythonContext to avoid symbol conflict in 3.7+
Nov 8, 2018
2c983a9
Use same name for Windows an Linux static lib before the extension
Nov 8, 2018
0bcf223
Add several needed static libs for Windows
Nov 8, 2018
8401a1c
Several improvements (see desc)
Nov 15, 2018
bd8c2d5
Several Improvements (II)
Nov 16, 2018
f964c46
Make iterators great (and working) again
Nov 16, 2018
ea7d615
fix usage of parsed string arguments in filter
Dec 5, 2018
1c73766
properly deallocate python objects
Dec 5, 2018
7cb563a
free encoding buffer
Dec 5, 2018
cd1d90d
bump versions
Dec 5, 2018
a55abc4
Unittests and other fixes
Dec 11, 2018
d74a514
Merge branch 'master' into v3
juanjux Dec 11, 2018
75170a6
Uncommented failed test
Dec 11, 2018
c4fd5be
Enabled unnitesting in travis
Dec 11, 2018
753efb4
Run docker and install python driver from travis
Dec 11, 2018
9876503
Commented out the node afected by SDK issue 340
Dec 12, 2018
7098328
Merge branch 'master' into v3
juanjux Dec 12, 2018
7ad8c6f
Remove Python 3.5 from Travis
Dec 12, 2018
a2752b7
Use range for grpcio and grpciotools
Dec 12, 2018
a99f5be
Fixed some of @bzz feedback from review
Dec 12, 2018
b983ea2
add error checks for iterators and clarify comments
Dec 13, 2018
9e3f415
Fixed from @zurk review (thanks!)
Dec 18, 2018
988eb5e
Merge branch 'v3' of https://github.com/dennwc/client-python into v3
Dec 18, 2018
ba93944
Merge branch 'master' into v3
juanjux Dec 18, 2018
d485273
Fixes and improvements from @vmarkovtsev review
Dec 18, 2018
66ccfed
PEP8 fix
Dec 18, 2018
a020666
Changed ModeDict to a Modes enum-like class
Dec 18, 2018
9b094aa
Allow to create Clients with an instanced grpc channel as suggested b…
Dec 18, 2018
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
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ include Makefile
include github.com/gogo/protobuf/gogoproto/gogo.proto
include gopkg.in/bblfsh/sdk.v1/protocol/generated.proto
include gopkg.in/bblfsh/sdk.v1/uast/generated.proto
include bblfsh/memtracker.h
include bblfsh/libuast/libuast.hpp
prune bblfsh/libuast
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@ python setup.py install

### Dependencies

You need to install `libxml2` and its header files. You also will need a `curl` cli tool to dowload `libuast`, and a `g++` for building [libtuast Python bindings](https://github.com/bblfsh/client-python/blob/0037d762563ab49b3daac8a7577f7103a5628fc6/setup.py#L17).
You also will need a `curl` cli tool to dowload `libuast`, and a `g++` for building [libtuast Python bindings](https://github.com/bblfsh/client-python/blob/0037d762563ab49b3daac8a7577f7103a5628fc6/setup.py#L17).
The command for Debian and derived distributions would be:

```bash
sudo apt install libxml2-dev
sudo apt install curl
sudo apt install build-essential
```
Expand All @@ -49,16 +48,18 @@ Please, read the [getting started](https://doc.bblf.sh/using-babelfish/getting-s
import bblfsh

client = bblfsh.BblfshClient("0.0.0.0:9432")
uast = client.parse("/path/to/file.py").uast
print(uast)
uast = client.parse("/path/to/file.py")
print(uast.load())

# "filter' allows you to use XPath queries to filter on result nodes:
print(bblfsh.filter(uast, "//Import[@roleImport and @roleDeclaration]//alias"))
it = uast.filter("//Import[@role='Import' and @role='Declaration']//alias")
for node in it:
print(node.load())

# filter\_[bool|string|number] must be used when using XPath functions returning
# these types:
print(bblfsh.filter_bool(uast, "boolean(//*[@strtOffset or @endOffset])"))
print(bblfsh.filter_string(uast, "name(//*[1])"))
print(bblfsh.filter_number(uast, "count(//*)"))
# filter must be used when using XPath functions returning these types:
print(uast.filter("boolean(//*[@strtOffset or @endOffset])"))
print(uast.filter("name(//*[1])"))
print(uast.filter("count(//*)"))

# You can also iterate on several tree iteration orders:
it = bblfsh.iterator(uast, bblfsh.TreeOrder.PRE_ORDER)
Expand Down
2 changes: 1 addition & 1 deletion bblfsh/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from bblfsh.client import BblfshClient
from bblfsh.pyuast import filter, filter_bool, filter_number, filter_string, iterator
from bblfsh.pyuast import decode, iterator, uast
from bblfsh.aliases import *

class TreeOrder:
Expand Down
43 changes: 21 additions & 22 deletions bblfsh/aliases.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
__all__ = ["DESCRIPTOR", "Node", "Position", "ParseResponse", "NativeParseResponse",
"ParseRequest", "NativeParseRequest", "VersionRequest", "ProtocolServiceStub"]

import importlib

from bblfsh.sdkversion import VERSION

# "in" is a reserved keyword in Python thus can't be used as package name, so
# we import by string
uast_module = importlib.import_module(
"bblfsh.gopkg.in.bblfsh.sdk.%s.uast.generated_pb2" % VERSION)
protocol_module = importlib.import_module(
"bblfsh.gopkg.in.bblfsh.sdk.%s.protocol.generated_pb2" % VERSION)
protocol_grpc_module = importlib.import_module(
"bblfsh.gopkg.in.bblfsh.sdk.%s.protocol.generated_pb2_grpc" % VERSION)

DESCRIPTOR = uast_module.DESCRIPTOR
Node = uast_module.Node
Position = uast_module.Position
ParseResponse = protocol_module.ParseResponse
NativeParseResponse = protocol_module.NativeParseResponse
ParseRequest = protocol_module.ParseRequest
NativeParseRequest = protocol_module.NativeParseRequest
VersionRequest = protocol_module.VersionRequest
SupportedLanguagesRequest = protocol_module.SupportedLanguagesRequest
SupportedLanguagesResponse = protocol_module.SupportedLanguagesResponse
ProtocolServiceStub = protocol_grpc_module.ProtocolServiceStub
uast_v2_module = importlib.import_module("bblfsh.gopkg.in.bblfsh.sdk.v2.uast.generated_pb2")
protocol_v2_module = importlib.import_module("bblfsh.gopkg.in.bblfsh.sdk.v2.protocol.generated_pb2")
protocol_grpc_v2_module = importlib.import_module("bblfsh.gopkg.in.bblfsh.sdk.v2.protocol.generated_pb2_grpc")
protocol_v1_module = importlib.import_module("bblfsh.gopkg.in.bblfsh.sdk.v1.protocol.generated_pb2")
protocol_grpc_v1_module = importlib.import_module("bblfsh.gopkg.in.bblfsh.sdk.v1.protocol.generated_pb2_grpc")

# Node = importlib.import_module(
# "bblfsh.gopkg.in.bblfsh.sdk.v2.uast.generated_pb2").Node

DESCRIPTOR = uast_v2_module.DESCRIPTOR
ParseRequest = protocol_v2_module.ParseRequest
ParseResponse = protocol_v2_module.ParseResponse
ParseError = protocol_v2_module.ParseError
Mode = protocol_v2_module.Mode
DriverStub = protocol_grpc_v2_module.DriverStub
DriverServicer = protocol_grpc_v2_module.DriverServicer

VersionRequest = protocol_v1_module.VersionRequest
SupportedLanguagesRequest = protocol_v1_module.SupportedLanguagesRequest
SupportedLanguagesResponse = protocol_v1_module.SupportedLanguagesResponse
ProtocolServiceStub = protocol_grpc_v1_module.ProtocolServiceStub
56 changes: 21 additions & 35 deletions bblfsh/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@

import grpc

from bblfsh.aliases import (ParseRequest, NativeParseRequest, VersionRequest,
ProtocolServiceStub, SupportedLanguagesRequest, SupportedLanguagesResponse)
from bblfsh.sdkversion import VERSION
from bblfsh.pyuast import decode as uast_decode

from bblfsh.aliases import ParseRequest, DriverStub, ProtocolServiceStub, VersionRequest, SupportedLanguagesRequest

# The following two insertions fix the broken pb import paths
sys.path.insert(0, os.path.join(os.path.dirname(__file__),
"gopkg/in/bblfsh/sdk/%s/protocol" % VERSION))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "gopkg/in/bblfsh/sdk/v1/protocol"))
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "gopkg/in/bblfsh/sdk/v2/protocol"))
sys.path.insert(0, os.path.dirname(__file__))


Expand All @@ -31,7 +31,8 @@ def __init__(self, endpoint):
:type endpoint: str
"""
self._channel = grpc.insecure_channel(endpoint)
self._stub = ProtocolServiceStub(self._channel)
self._stub_v1 = ProtocolServiceStub(self._channel)
self._stub_v2 = DriverStub(self._channel)

@staticmethod
def _check_utf8(text):
Expand All @@ -48,7 +49,7 @@ def _get_contents(contents, filename):
BblfshClient._check_utf8(contents)
return contents

def parse(self, filename, language=None, contents=None, timeout=None):
def parse(self, filename, language=None, contents=None, mode=None, raw=False, timeout=None):
"""
Queries the Babelfish server and receives the UAST response for the specified
file.
Expand All @@ -60,6 +61,8 @@ def parse(self, filename, language=None, contents=None, timeout=None):
currently supported languages. None means autodetect.
:param contents: The contents of the file. IF None, it is read from \
filename.
:param mode: UAST transformation mode.
:param raw: Return raw binary UAST without decoding it.
:param timeout: The request timeout in seconds.
:type filename: str
:type language: str
Expand All @@ -71,47 +74,30 @@ def parse(self, filename, language=None, contents=None, timeout=None):
contents = self._get_contents(contents, filename)
request = ParseRequest(filename=os.path.basename(filename),
content=contents,
mode=mode,
language=self._scramble_language(language))
return self._stub.Parse(request, timeout=timeout)

def native_parse(self, filename, language=None, contents=None, timeout=None):
response = self._stub_v2.Parse(request, timeout=timeout)
"""
Queries the Babelfish server and receives the native AST response for the specified
file.

:param filename: The path to the file. Can be arbitrary if contents \
is not None.
:param language: The programming language of the file. Refer to \
https://doc.bblf.sh/languages.html for the list of \
currently supported languages. None means autodetect.
:param contents: The contents of the file. IF None, it is read from \
filename.
:param timeout: The request timeout in seconds.
:type filename: str
:type language: str
:type contents: str
:type timeout: float
:return: Native AST object.
TODO: return detected language
TODO: handle syntax errors
"""

contents = self._get_contents(contents, filename)
request = NativeParseRequest(filename=os.path.basename(filename),
content=contents,
language=self._scramble_language(language))
return self._stub.NativeParse(request, timeout=timeout)
if raw:
return response.uast
ctx = uast_decode(response.uast, format=0)
return ctx

def supported_languages(self):
sup_response = self._stub.SupportedLanguages(SupportedLanguagesRequest())
sup_response = self._stub_v1.SupportedLanguages(SupportedLanguagesRequest())
return sup_response.languages

def version(self):
"""
Queries the Babelfish server for version and runtime information.

:return: A dictionary with the keys "version" for the semantic version and
"build" for the build timestamp.
# "build" for the build timestamp.
"""
return self._stub.Version(VersionRequest())
return self._stub_v1.Version(VersionRequest())

@staticmethod
def _scramble_language(lang):
Expand Down
35 changes: 0 additions & 35 deletions bblfsh/memtracker.cc

This file was deleted.

25 changes: 0 additions & 25 deletions bblfsh/memtracker.h

This file was deleted.

Loading