pygraphile 0.2.0__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pygraphile
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: A Python library inspired by PostGraphile - automatically generates GraphQL APIs from databases. Currently supports SQLite with plans for additional database support.
5
5
  Project-URL: Homepage, https://github.com/dshaw0004/pygraphile
6
6
  Project-URL: Repository, https://github.com/dshaw0004/pygraphile
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pygraphile"
3
- version = "0.2.0"
3
+ version = "0.3.0"
4
4
  description = "A Python library inspired by PostGraphile - automatically generates GraphQL APIs from databases. Currently supports SQLite with plans for additional database support."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -1,4 +1,3 @@
1
- import sqlite3
2
1
  """
3
2
  PyGraphile - A Python library for automatically generating GraphQL APIs from databases.
4
3
 
@@ -10,8 +9,6 @@ Currently supports SQLite with plans for PostgreSQL, MySQL, and other databases.
10
9
  from .main import PyGraphile
11
10
  from .utils import get_schema_from_table_name, generate_query_type, generate_type_defs, SQL_TO_GRAPHQL
12
11
 
13
- __version__ = "0.1.0"
12
+ __version__ = "0.3.0"
14
13
  __author__ = "dshaw0004"
15
14
  __all__ = ["__version__", "PyGraphile", "get_schema_from_table_name", "generate_type_defs", "generate_query_type", "SQL_TO_GRAPHQL"]
16
-
17
-
@@ -0,0 +1,66 @@
1
+ import sqlite3
2
+
3
+ from ariadne import QueryType, make_executable_schema
4
+ from ariadne.asgi import GraphQL
5
+
6
+ from .utils import get_schema_from_table_name, generate_query_type, generate_type_defs
7
+
8
+ __all__ = ["PyGraphile"]
9
+
10
+
11
+ class PyGraphile:
12
+ def __init__(
13
+ self,
14
+ db_name: str = 'pygraphile.sqlite',
15
+ db_type: str = 'sqlite3',
16
+ migration_folder: str = 'nomigration',
17
+ debug: bool = False,
18
+ ):
19
+ if db_type != 'sqlite3':
20
+ raise ValueError(f"Unsupported database type: '{db_type}'. Currently only 'sqlite3' is supported.")
21
+
22
+ if migration_folder != 'nomigration':
23
+ # TODO: apply migration
24
+ print('need to implement this')
25
+
26
+ self._debug = debug
27
+ self.con = sqlite3.connect(db_name)
28
+ self.con.row_factory = sqlite3.Row
29
+ self.cursor = self.con.cursor()
30
+
31
+ result: list[tuple[str,]] = self.cursor.execute(
32
+ "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"
33
+ ).fetchall()
34
+ self.tables = [res[0] for res in result]
35
+ print(f'Following tables detected: {self.tables}')
36
+
37
+ self.table_schemas = {
38
+ table: get_schema_from_table_name(self.cursor, table)
39
+ for table in self.tables
40
+ }
41
+
42
+ self.gql_type_def: str = generate_type_defs(self.table_schemas)
43
+ self.gql_query_types: str = generate_query_type(self.table_schemas)
44
+
45
+ query = QueryType()
46
+
47
+ # dynamically attach resolvers
48
+ for table in self.tables:
49
+ query.set_field(table, self.make_resolver(table))
50
+
51
+ type_defs = self.gql_type_def + "\n" + self.gql_query_types
52
+ self.schema = make_executable_schema(type_defs, query)
53
+
54
+ def get_query_app(self):
55
+ return GraphQL(self.schema, debug=self._debug)
56
+
57
+ def make_resolver(self, table_name: str):
58
+ # Quote the table name to prevent SQL injection
59
+ safe_table = table_name.replace('"', '""')
60
+
61
+ def resolver(_, info, **kwargs):
62
+ sql = f'SELECT * FROM "{safe_table}"'
63
+ rows = self.cursor.execute(sql).fetchall()
64
+ return [dict(row) for row in rows]
65
+
66
+ return resolver
@@ -29,7 +29,7 @@ def generate_type_defs(tables):
29
29
  for table_name, columns in tables.items():
30
30
  fields = []
31
31
  for col in columns:
32
- gql_type = SQL_TO_GRAPHQL.get(col["type"].upper(), "String")
32
+ gql_type = SQL_TO_GRAPHQL.get((col["type"] or "").upper(), "String")
33
33
  not_null = "!" if col["notnull"] else ""
34
34
  fields.append(f"{col['name']}: {gql_type}{not_null}")
35
35
  type_def = f"type {table_name.capitalize()} {{\n " + \
@@ -7,7 +7,7 @@ def test_version():
7
7
  """Test that version is defined."""
8
8
  assert hasattr(pygraphile, "__version__")
9
9
  assert isinstance(pygraphile.__version__, str)
10
- assert pygraphile.__version__ == "0.1.0"
10
+ assert pygraphile.__version__ == "0.3.0"
11
11
 
12
12
 
13
13
  def test_module_imports():
@@ -1,70 +0,0 @@
1
- import sqlite3
2
-
3
- from ariadne import QueryType, make_executable_schema, gql
4
- from ariadne.asgi import GraphQL
5
- from fastapi import FastAPI
6
-
7
- from utils import get_schema_from_table_name, generate_query_type, generate_type_defs
8
-
9
- __all__ = ["PyGraphile"]
10
-
11
-
12
- class PyGraphile:
13
- def __init__(self,
14
- db_name: str = 'pygraphile.sqlite',
15
- db_type: str = 'sqlite3',
16
- migration_folder: str = 'nomigration',
17
- ):
18
-
19
- if 'sqlite3' != db_type:
20
- print('this database is not supported yet')
21
- exit(1)
22
-
23
- if 'nomigration' != migration_folder:
24
- # TODO: apply migration
25
- print('need to implement this')
26
-
27
- self.con = sqlite3.connect(db_name)
28
- self.con.row_factory = sqlite3.Row
29
- self.cursor = self.con.cursor()
30
-
31
- result: list[tuple[str,]] = self.cursor.execute(
32
- "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'").fetchall()
33
- self.tables = [res[0] for res in result]
34
- print(f'Following tables detected {self.tables}')
35
-
36
- self.table_schemas = {table: get_schema_from_table_name(
37
- self.cursor, table) for table in self.tables}
38
-
39
- self.gql_type_def: str = generate_type_defs(self.table_schemas)
40
- self.gql_query_types: str = generate_query_type(self.table_schemas)
41
- print(self.gql_type_def)
42
- print(self.gql_query_types)
43
-
44
- query = QueryType()
45
-
46
- # dynamically attach resolvers
47
- for table in self.tables:
48
- query.set_field(table, self.make_resolver(table))
49
-
50
- type_defs = self.gql_type_def + "\n" + self.gql_query_types
51
- self.schema = make_executable_schema(type_defs, query)
52
-
53
- def get_query_app(self):
54
- return GraphQL(self.schema, debug=True)
55
-
56
- def make_resolver(self, table_name: str):
57
- def resolver(_, info, **kwargs):
58
- sql = f"SELECT * FROM {table_name} LIMIT 1"
59
- rows = self.cursor.execute(sql).fetchall()
60
- return [dict(row) for row in rows]
61
- return resolver
62
-
63
-
64
- # if __name__ == "__main__":
65
- # # initialize FastAPI
66
- # app = FastAPI()
67
- # # initialize PyGraphile
68
- # pg = PyGraphile(db_name="pygraphile.sqlite")
69
- # # mount Ariadne GraphQL app at /graphql
70
- # app.mount("/graphql", pg.get_query_app())
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes