@graphql-codegen/python-common 0.0.1 → 0.0.2

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 CHANGED
@@ -1,50 +1,40 @@
1
1
  {
2
2
  "name": "@graphql-codegen/python-common",
3
- "version": "0.0.1",
4
- "type": "module",
3
+ "version": "0.0.2",
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": "dist/cjs/index.js",
12
- "module": "dist/esm/index.js",
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": "./dist/typings/index.d.cts",
17
- "default": "./dist/cjs/index.js"
26
+ "types": "./typings/index.d.cts",
27
+ "default": "./cjs/index.js"
18
28
  },
19
29
  "import": {
20
- "types": "./dist/typings/index.d.ts",
21
- "default": "./dist/esm/index.js"
30
+ "types": "./typings/index.d.ts",
31
+ "default": "./esm/index.js"
22
32
  },
23
33
  "default": {
24
- "types": "./dist/typings/index.d.ts",
25
- "default": "./dist/esm/index.js"
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
@@ -1,3 +0,0 @@
1
- export * from './keywords.js';
2
- export * from './member-naming.js';
3
- export * from './scalars.js';
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
- }
@@ -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