@graphql-codegen/python-common 0.0.1 → 0.0.2-alpha-20261029093428-bb94591c48dc485d04089639f4ca0f124e339666
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.
- package/package.json +21 -31
- package/dist/README.md +0 -28
- package/dist/package.json +0 -40
- package/src/index.ts +0 -3
- package/src/keywords.ts +0 -56
- package/src/member-naming.ts +0 -48
- package/src/scalars.ts +0 -13
- package/tests/python-common.spec.ts +0 -113
- package/vitest.config.ts +0 -12
- /package/{dist/cjs → cjs}/index.js +0 -0
- /package/{dist/cjs → cjs}/keywords.js +0 -0
- /package/{dist/cjs → cjs}/member-naming.js +0 -0
- /package/{dist/cjs → cjs}/package.json +0 -0
- /package/{dist/cjs → cjs}/scalars.js +0 -0
- /package/{dist/esm → esm}/index.js +0 -0
- /package/{dist/esm → esm}/keywords.js +0 -0
- /package/{dist/esm → esm}/member-naming.js +0 -0
- /package/{dist/esm → esm}/scalars.js +0 -0
- /package/{dist/typings → typings}/index.d.cts +0 -0
- /package/{dist/typings → typings}/index.d.ts +0 -0
- /package/{dist/typings → typings}/keywords.d.cts +0 -0
- /package/{dist/typings → typings}/keywords.d.ts +0 -0
- /package/{dist/typings → typings}/member-naming.d.cts +0 -0
- /package/{dist/typings → typings}/member-naming.d.ts +0 -0
- /package/{dist/typings → typings}/scalars.d.cts +0 -0
- /package/{dist/typings → typings}/scalars.d.ts +0 -0
package/package.json
CHANGED
|
@@ -1,50 +1,40 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graphql-codegen/python-common",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"type": "module",
|
|
3
|
+
"version": "0.0.2-alpha-20261029093428-bb94591c48dc485d04089639f4ca0f124e339666",
|
|
5
4
|
"description": "Shared Python-specific helpers (reserved keywords, scalar mapping, identifier naming) for @graphql-codegen/python and @graphql-codegen/python-operations.",
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@graphql-codegen/visitor-plugin-common": "^6.3.0",
|
|
8
|
+
"change-case-all": "1.0.15",
|
|
9
|
+
"tslib": "^2.8.1"
|
|
10
|
+
},
|
|
6
11
|
"repository": "git@github.com:dotansimha/graphql-code-generator-community.git",
|
|
7
12
|
"license": "MIT",
|
|
8
13
|
"engines": {
|
|
9
14
|
"node": ">= 16.0.0"
|
|
10
15
|
},
|
|
11
|
-
"main": "
|
|
12
|
-
"module": "
|
|
16
|
+
"main": "cjs/index.js",
|
|
17
|
+
"module": "esm/index.js",
|
|
18
|
+
"typings": "typings/index.d.ts",
|
|
19
|
+
"typescript": {
|
|
20
|
+
"definition": "typings/index.d.ts"
|
|
21
|
+
},
|
|
22
|
+
"type": "module",
|
|
13
23
|
"exports": {
|
|
14
24
|
".": {
|
|
15
25
|
"require": {
|
|
16
|
-
"types": "./
|
|
17
|
-
"default": "./
|
|
26
|
+
"types": "./typings/index.d.cts",
|
|
27
|
+
"default": "./cjs/index.js"
|
|
18
28
|
},
|
|
19
29
|
"import": {
|
|
20
|
-
"types": "./
|
|
21
|
-
"default": "./
|
|
30
|
+
"types": "./typings/index.d.ts",
|
|
31
|
+
"default": "./esm/index.js"
|
|
22
32
|
},
|
|
23
33
|
"default": {
|
|
24
|
-
"types": "./
|
|
25
|
-
"default": "./
|
|
34
|
+
"types": "./typings/index.d.ts",
|
|
35
|
+
"default": "./esm/index.js"
|
|
26
36
|
}
|
|
27
37
|
},
|
|
28
38
|
"./package.json": "./package.json"
|
|
29
|
-
},
|
|
30
|
-
"typings": "dist/typings/index.d.ts",
|
|
31
|
-
"scripts": {
|
|
32
|
-
"lint": "eslint **/*.ts"
|
|
33
|
-
},
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"@graphql-codegen/visitor-plugin-common": "^6.3.0",
|
|
36
|
-
"change-case-all": "1.0.15",
|
|
37
|
-
"tslib": "^2.8.1"
|
|
38
|
-
},
|
|
39
|
-
"devDependencies": {
|
|
40
|
-
"@graphql-codegen/testing": "4.0.5"
|
|
41
|
-
},
|
|
42
|
-
"publishConfig": {
|
|
43
|
-
"directory": "dist",
|
|
44
|
-
"access": "public"
|
|
45
|
-
},
|
|
46
|
-
"sideEffects": false,
|
|
47
|
-
"typescript": {
|
|
48
|
-
"definition": "dist/typings/index.d.ts"
|
|
49
39
|
}
|
|
50
|
-
}
|
|
40
|
+
}
|
package/dist/README.md
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# `@graphql-codegen/python-common`
|
|
2
|
-
|
|
3
|
-
Shared Python-specific helpers for the `@graphql-codegen/python` plugin family (`python`,
|
|
4
|
-
`python-operations`): the naming knowledge those plugins must agree on so their generated classes
|
|
5
|
-
line up exactly, kept in one place.
|
|
6
|
-
|
|
7
|
-
Modeled on `@graphql-codegen/c-sharp-common` / `@graphql-codegen/java-common`, which play the same
|
|
8
|
-
role for their respective language families.
|
|
9
|
-
|
|
10
|
-
## What's here
|
|
11
|
-
|
|
12
|
-
- **`PYTHON_KEYWORDS`** / **`PY_IDENT_RE`** / **`isValidClassAttr`** — the CPython reserved-word set
|
|
13
|
-
(incl. the soft keywords `match`/`case`) and identifier validation used to decide when a GraphQL
|
|
14
|
-
name needs escaping.
|
|
15
|
-
- **`PYTHON_SCALARS`** — the default GraphQL scalar → Python type mapping (custom scalars fall back
|
|
16
|
-
to `Any`).
|
|
17
|
-
- **`pythonFieldName`** / **`isReservedField`** — convert a GraphQL name to `snake_case` for use as
|
|
18
|
-
a Python identifier, escaping reserved keywords with a trailing `_`.
|
|
19
|
-
- **`pascalCase`** / **`constantCase`** — the class-name and document-constant casing helpers,
|
|
20
|
-
re-exported from `change-case-all`.
|
|
21
|
-
|
|
22
|
-
This package is the **single place in the family that depends on `change-case-all`**:
|
|
23
|
-
`pythonFieldName`, `pascalCase`, and `constantCase` all route through it, so every plugin gets the
|
|
24
|
-
same acronym-splitting behavior (`GetHTTPStatus` → `GetHttpStatus` / `get_http_status`) and no
|
|
25
|
-
consumer imports `change-case-all` or hand-rolls the rules itself. `python` and `python-operations`
|
|
26
|
-
get PascalCase names from `BaseVisitor.convertName` (which uses `change-case-all`); a plugin that
|
|
27
|
-
doesn't extend the base visitor can use the `pascalCase` / `constantCase` exported here to produce
|
|
28
|
-
byte-identical names.
|
package/dist/package.json
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@graphql-codegen/python-common",
|
|
3
|
-
"version": "0.0.1",
|
|
4
|
-
"description": "Shared Python-specific helpers (reserved keywords, scalar mapping, identifier naming) for @graphql-codegen/python and @graphql-codegen/python-operations.",
|
|
5
|
-
"sideEffects": false,
|
|
6
|
-
"dependencies": {
|
|
7
|
-
"@graphql-codegen/visitor-plugin-common": "^6.3.0",
|
|
8
|
-
"change-case-all": "1.0.15",
|
|
9
|
-
"tslib": "^2.8.1"
|
|
10
|
-
},
|
|
11
|
-
"repository": "git@github.com:dotansimha/graphql-code-generator-community.git",
|
|
12
|
-
"license": "MIT",
|
|
13
|
-
"engines": {
|
|
14
|
-
"node": ">= 16.0.0"
|
|
15
|
-
},
|
|
16
|
-
"main": "cjs/index.js",
|
|
17
|
-
"module": "esm/index.js",
|
|
18
|
-
"typings": "typings/index.d.ts",
|
|
19
|
-
"typescript": {
|
|
20
|
-
"definition": "typings/index.d.ts"
|
|
21
|
-
},
|
|
22
|
-
"type": "module",
|
|
23
|
-
"exports": {
|
|
24
|
-
".": {
|
|
25
|
-
"require": {
|
|
26
|
-
"types": "./typings/index.d.cts",
|
|
27
|
-
"default": "./cjs/index.js"
|
|
28
|
-
},
|
|
29
|
-
"import": {
|
|
30
|
-
"types": "./typings/index.d.ts",
|
|
31
|
-
"default": "./esm/index.js"
|
|
32
|
-
},
|
|
33
|
-
"default": {
|
|
34
|
-
"types": "./typings/index.d.ts",
|
|
35
|
-
"default": "./esm/index.js"
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
"./package.json": "./package.json"
|
|
39
|
-
}
|
|
40
|
-
}
|
package/src/index.ts
DELETED
package/src/keywords.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Python reserved keywords (from the CPython `keyword` module, incl. the soft
|
|
3
|
-
* keywords `match`/`case`). Names matching one of these get a trailing `_`
|
|
4
|
-
* wherever they'd otherwise be used as a Python identifier.
|
|
5
|
-
*/
|
|
6
|
-
export const PYTHON_KEYWORDS = new Set<string>([
|
|
7
|
-
'False',
|
|
8
|
-
'None',
|
|
9
|
-
'True',
|
|
10
|
-
'and',
|
|
11
|
-
'as',
|
|
12
|
-
'assert',
|
|
13
|
-
'async',
|
|
14
|
-
'await',
|
|
15
|
-
'break',
|
|
16
|
-
'class',
|
|
17
|
-
'continue',
|
|
18
|
-
'def',
|
|
19
|
-
'del',
|
|
20
|
-
'elif',
|
|
21
|
-
'else',
|
|
22
|
-
'except',
|
|
23
|
-
'finally',
|
|
24
|
-
'for',
|
|
25
|
-
'from',
|
|
26
|
-
'global',
|
|
27
|
-
'if',
|
|
28
|
-
'import',
|
|
29
|
-
'in',
|
|
30
|
-
'is',
|
|
31
|
-
'lambda',
|
|
32
|
-
'nonlocal',
|
|
33
|
-
'not',
|
|
34
|
-
'or',
|
|
35
|
-
'pass',
|
|
36
|
-
'raise',
|
|
37
|
-
'return',
|
|
38
|
-
'try',
|
|
39
|
-
'while',
|
|
40
|
-
'with',
|
|
41
|
-
'yield',
|
|
42
|
-
'match',
|
|
43
|
-
'case',
|
|
44
|
-
]);
|
|
45
|
-
|
|
46
|
-
/** A valid Python identifier (matches the GraphQL Name grammar plus keywords). */
|
|
47
|
-
export const PY_IDENT_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Whether `name` can be used as a plain Python class/dict attribute: it must
|
|
51
|
-
* be a valid identifier AND not a reserved keyword. When it cannot, the
|
|
52
|
-
* containing `TypedDict` must be emitted with functional syntax.
|
|
53
|
-
*/
|
|
54
|
-
export function isValidClassAttr(name: string): boolean {
|
|
55
|
-
return PY_IDENT_RE.test(name) && !PYTHON_KEYWORDS.has(name);
|
|
56
|
-
}
|
package/src/member-naming.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { constantCase, pascalCase, snakeCase } from 'change-case-all';
|
|
2
|
-
import { PYTHON_KEYWORDS } from './keywords.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* This module is the single place in the Python plugin family that imports
|
|
6
|
-
* `change-case-all`. The plugins route their snake / pascal / constant casing
|
|
7
|
-
* through these exports so the generated names line up exactly and no consumer
|
|
8
|
-
* hand-rolls (or diverges on) the acronym-splitting rules.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* snake_case a GraphQL name for use as a Python identifier (field, method, or
|
|
13
|
-
* document-constant base name), appending a trailing `_` when the result
|
|
14
|
-
* collides with a reserved keyword.
|
|
15
|
-
*
|
|
16
|
-
* Uses change-case-all's `snakeCase` — the same implementation
|
|
17
|
-
* `@graphql-codegen/python`'s `pascalCase` (via `BaseVisitor.convertName`)
|
|
18
|
-
* already relies on — so acronym runs split identically on both sides, e.g.
|
|
19
|
-
* `httpURL` -> `http_url` lines up with `HttpUrl`. A hand-rolled
|
|
20
|
-
* implementation previously diverged for `pascalCase` on `GetHTTPStatus`.
|
|
21
|
-
*
|
|
22
|
-
* Each consumer previously duplicated this exact function under a locally
|
|
23
|
-
* meaningful name (`methodName`, `pyFieldName`, `snakeFieldName`); import and
|
|
24
|
-
* alias it the same way here instead of re-implementing it.
|
|
25
|
-
*/
|
|
26
|
-
export function pythonFieldName(name: string): string {
|
|
27
|
-
const snake = snakeCase(name);
|
|
28
|
-
return PYTHON_KEYWORDS.has(snake) ? `${snake}_` : snake;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Whether a GraphQL response key maps to a Python reserved keyword once
|
|
33
|
-
* snake-cased (before any trailing-`_` escaping is applied).
|
|
34
|
-
*/
|
|
35
|
-
export function isReservedField(name: string): boolean {
|
|
36
|
-
return PYTHON_KEYWORDS.has(snakeCase(name));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* PascalCase a name for a generated Python class / result-type name.
|
|
41
|
-
*
|
|
42
|
-
* This is the exact `change-case-all` `pascalCase` that
|
|
43
|
-
* `@graphql-codegen/python` and `@graphql-codegen/python-operations` use via
|
|
44
|
-
* `BaseVisitor.convertName`, re-exported so a plugin that does NOT extend the
|
|
45
|
-
* base visitor produces byte-identical class names, including acronym runs,
|
|
46
|
-
* e.g. `GetHTTPStatus` -> `GetHttpStatus`.
|
|
47
|
-
*/
|
|
48
|
-
export { constantCase, pascalCase };
|
package/src/scalars.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { NormalizedScalarsMap } from '@graphql-codegen/visitor-plugin-common';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Default GraphQL scalar -> Python type mapping. Custom scalars fall back to
|
|
5
|
-
* `Any`.
|
|
6
|
-
*/
|
|
7
|
-
export const PYTHON_SCALARS: NormalizedScalarsMap = {
|
|
8
|
-
ID: { input: 'str', output: 'str' },
|
|
9
|
-
String: { input: 'str', output: 'str' },
|
|
10
|
-
Int: { input: 'int', output: 'int' },
|
|
11
|
-
Float: { input: 'float', output: 'float' },
|
|
12
|
-
Boolean: { input: 'bool', output: 'bool' },
|
|
13
|
-
};
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import {
|
|
3
|
-
constantCase,
|
|
4
|
-
isReservedField,
|
|
5
|
-
isValidClassAttr,
|
|
6
|
-
pascalCase,
|
|
7
|
-
PY_IDENT_RE,
|
|
8
|
-
PYTHON_KEYWORDS,
|
|
9
|
-
PYTHON_SCALARS,
|
|
10
|
-
pythonFieldName,
|
|
11
|
-
} from '../src/index.js';
|
|
12
|
-
|
|
13
|
-
describe('@graphql-codegen/python-common', () => {
|
|
14
|
-
describe('PYTHON_KEYWORDS', () => {
|
|
15
|
-
it('contains hard keywords', () => {
|
|
16
|
-
expect(PYTHON_KEYWORDS.has('class')).toBe(true);
|
|
17
|
-
expect(PYTHON_KEYWORDS.has('from')).toBe(true);
|
|
18
|
-
expect(PYTHON_KEYWORDS.has('import')).toBe(true);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it('contains the soft keywords match/case', () => {
|
|
22
|
-
expect(PYTHON_KEYWORDS.has('match')).toBe(true);
|
|
23
|
-
expect(PYTHON_KEYWORDS.has('case')).toBe(true);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('does not flag ordinary identifiers', () => {
|
|
27
|
-
expect(PYTHON_KEYWORDS.has('id')).toBe(false);
|
|
28
|
-
expect(PYTHON_KEYWORDS.has('name')).toBe(false);
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
describe('PY_IDENT_RE / isValidClassAttr', () => {
|
|
33
|
-
it('accepts valid identifiers that are not keywords', () => {
|
|
34
|
-
expect(PY_IDENT_RE.test('user_id')).toBe(true);
|
|
35
|
-
expect(isValidClassAttr('user_id')).toBe(true);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('rejects reserved keywords even though they match the identifier regex', () => {
|
|
39
|
-
expect(PY_IDENT_RE.test('class')).toBe(true);
|
|
40
|
-
expect(isValidClassAttr('class')).toBe(false);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it('rejects non-identifier strings', () => {
|
|
44
|
-
expect(isValidClassAttr('2fast')).toBe(false);
|
|
45
|
-
expect(isValidClassAttr('my-field')).toBe(false);
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
describe('PYTHON_SCALARS', () => {
|
|
50
|
-
it('maps built-in GraphQL scalars to native Python types', () => {
|
|
51
|
-
expect(PYTHON_SCALARS.ID).toEqual({ input: 'str', output: 'str' });
|
|
52
|
-
expect(PYTHON_SCALARS.Int).toEqual({ input: 'int', output: 'int' });
|
|
53
|
-
expect(PYTHON_SCALARS.Float).toEqual({ input: 'float', output: 'float' });
|
|
54
|
-
expect(PYTHON_SCALARS.Boolean).toEqual({ input: 'bool', output: 'bool' });
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
describe('pythonFieldName', () => {
|
|
59
|
-
it('converts camelCase to snake_case', () => {
|
|
60
|
-
expect(pythonFieldName('createdAt')).toBe('created_at');
|
|
61
|
-
expect(pythonFieldName('firstName')).toBe('first_name');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('splits acronym runs the same way change-case pascalCase does', () => {
|
|
65
|
-
expect(pythonFieldName('GetHTTPStatus')).toBe('get_http_status');
|
|
66
|
-
expect(pythonFieldName('httpURL')).toBe('http_url');
|
|
67
|
-
expect(pythonFieldName('ABTest')).toBe('ab_test');
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
it('escapes reserved keywords with a trailing underscore', () => {
|
|
71
|
-
expect(pythonFieldName('from')).toBe('from_');
|
|
72
|
-
expect(pythonFieldName('class')).toBe('class_');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('leaves non-keyword snake_case names untouched', () => {
|
|
76
|
-
expect(pythonFieldName('user_id')).toBe('user_id');
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
describe('isReservedField', () => {
|
|
81
|
-
it('is true when the snake_cased name is a reserved keyword', () => {
|
|
82
|
-
expect(isReservedField('from')).toBe(true);
|
|
83
|
-
expect(isReservedField('Class')).toBe(true); // snake_cases to "class"
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('is false when the snake_cased name merely contains a keyword as a substring', () => {
|
|
87
|
-
expect(isReservedField('className')).toBe(false); // snake_cases to "class_name"
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('is false for ordinary field names', () => {
|
|
91
|
-
expect(isReservedField('createdAt')).toBe(false);
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
describe('pascalCase', () => {
|
|
96
|
-
it('PascalCases names for class / result types', () => {
|
|
97
|
-
expect(pascalCase('getUsers')).toBe('GetUsers');
|
|
98
|
-
expect(pascalCase('get_users')).toBe('GetUsers');
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('lowercases acronym runs so class names line up with BaseVisitor.convertName', () => {
|
|
102
|
-
expect(pascalCase('GetHTTPStatus')).toBe('GetHttpStatus');
|
|
103
|
-
expect(pascalCase('httpURL')).toBe('HttpUrl');
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
describe('constantCase', () => {
|
|
108
|
-
it('CONSTANT_CASEs names for document constants', () => {
|
|
109
|
-
expect(constantCase('getUsers')).toBe('GET_USERS');
|
|
110
|
-
expect(constantCase('GetHTTPStatus')).toBe('GET_HTTP_STATUS');
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
});
|
package/vitest.config.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { defineProject, mergeConfig } from 'vitest/config';
|
|
2
|
-
import { sharedConfig } from '../../../../vitest.config.js';
|
|
3
|
-
|
|
4
|
-
export default mergeConfig(
|
|
5
|
-
sharedConfig,
|
|
6
|
-
defineProject({
|
|
7
|
-
test: {
|
|
8
|
-
name: 'python-common',
|
|
9
|
-
include: ['**/*.spec.ts'],
|
|
10
|
-
},
|
|
11
|
-
}),
|
|
12
|
-
);
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|