├── tools
├── schematics
│ └── .gitkeep
└── tsconfig.tools.json
├── .github
└── FUNDING.yml
├── .prettierrc
├── packages
├── nx-python
│ ├── src
│ │ ├── schematics
│ │ │ └── nx-python
│ │ │ │ ├── files
│ │ │ │ ├── flask
│ │ │ │ │ ├── src
│ │ │ │ │ │ ├── tests
│ │ │ │ │ │ │ └── gabbi
│ │ │ │ │ │ │ │ ├── index.yaml.template
│ │ │ │ │ │ │ │ └── name.yaml.template
│ │ │ │ │ │ └── name
│ │ │ │ │ │ │ ├── api_doc.py.template
│ │ │ │ │ │ │ ├── application.py.template
│ │ │ │ │ │ │ ├── manage.py.template
│ │ │ │ │ │ │ └── __init__.py.template
│ │ │ │ │ ├── wadl
│ │ │ │ │ │ ├── name-wadl.xml.template
│ │ │ │ │ │ └── wadl.xsl.template
│ │ │ │ │ ├── requirements.txt
│ │ │ │ │ ├── Readme.md.template
│ │ │ │ │ └── setup.py.template
│ │ │ │ ├── default
│ │ │ │ │ └── src
│ │ │ │ │ │ ├── hello.py.template
│ │ │ │ │ │ └── test_hello.py.template
│ │ │ │ └── django
│ │ │ │ │ ├── src
│ │ │ │ │ ├── asgi.py.template
│ │ │ │ │ ├── wsgi.py.template
│ │ │ │ │ ├── urls.py.template
│ │ │ │ │ └── settings.py.template
│ │ │ │ │ └── manage.py.template
│ │ │ │ ├── schema.d.ts
│ │ │ │ ├── schematic.spec.ts
│ │ │ │ ├── target-options.ts
│ │ │ │ ├── schema.json
│ │ │ │ └── schematic.ts
│ │ ├── index.ts
│ │ ├── builders
│ │ │ ├── lint
│ │ │ │ ├── schema.d.ts
│ │ │ │ ├── schema.json
│ │ │ │ ├── builder.ts
│ │ │ │ └── builder.spec.ts
│ │ │ ├── test
│ │ │ │ ├── schema.d.ts
│ │ │ │ ├── schema.json
│ │ │ │ ├── builder.ts
│ │ │ │ └── builder.spec.ts
│ │ │ ├── build
│ │ │ │ ├── schema.d.ts
│ │ │ │ ├── schema.json
│ │ │ │ ├── builder.ts
│ │ │ │ └── builder.spec.ts
│ │ │ └── serve
│ │ │ │ ├── schema.json
│ │ │ │ ├── schema.d.ts
│ │ │ │ ├── builder.ts
│ │ │ │ └── builder.spec.ts
│ │ ├── project-graph
│ │ │ ├── has-python-files.ts
│ │ │ └── index.ts
│ │ └── utils
│ │ │ ├── py-utils.ts
│ │ │ └── command.ts
│ ├── .eslintrc
│ ├── README.md
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ ├── tsconfig.spec.json
│ ├── jest.config.js
│ ├── collection.json
│ ├── package.json
│ ├── builders.json
│ └── READM.md
└── python-graph
│ ├── .eslintrc
│ ├── README.md
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ ├── tsconfig.spec.json
│ ├── jest.config.js
│ ├── src
│ ├── has-python-files.ts
│ └── index.ts
│ └── package.json
├── .prettierignore
├── nx-python-nx-python-1.0.2.tgz
├── e2e
└── nx-python-e2e
│ ├── tsconfig.spec.json
│ ├── tsconfig.json
│ ├── jest.config.js
│ └── tests
│ └── nx-python.test.ts
├── .editorconfig
├── jest.config.js
├── tsconfig.base.json
├── .gitignore
├── PULL_REQUEST_TEMPLATE.md
├── nx.json
├── LICENSE
├── ISSUE_TEMPLATE.md
├── .eslintrc
├── package.json
├── migrations.json
├── CODE_OF_CONDUCT.md
├── workspace.json
└── README.md
/tools/schematics/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: alphacentauri82
2 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true
3 | }
4 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/flask/src/tests/gabbi/index.yaml.template:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/flask/src/tests/gabbi/name.yaml.template:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/nx-python/src/index.ts:
--------------------------------------------------------------------------------
1 | export type CommandType = 'build' | 'lint' | 'serve' | 'test';
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | # Add files here to ignore them from prettier formatting
2 |
3 | /dist
4 | /coverage
5 |
--------------------------------------------------------------------------------
/packages/nx-python/.eslintrc:
--------------------------------------------------------------------------------
1 | { "extends": "../../.eslintrc", "rules": {}, "ignorePatterns": ["!**/*"] }
2 |
--------------------------------------------------------------------------------
/packages/python-graph/.eslintrc:
--------------------------------------------------------------------------------
1 | { "extends": "../../.eslintrc", "rules": {}, "ignorePatterns": ["!**/*"] }
2 |
--------------------------------------------------------------------------------
/nx-python-nx-python-1.0.2.tgz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hogarthww-labs/nx-python/HEAD/nx-python-nx-python-1.0.2.tgz
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/lint/schema.d.ts:
--------------------------------------------------------------------------------
1 | import { JsonObject } from '@angular-devkit/core'
2 |
3 | export interface LintBuilderSchema extends JsonObject {
4 | outputPath?: string
5 | main?: string
6 | }
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/test/schema.d.ts:
--------------------------------------------------------------------------------
1 | import { JsonObject } from '@angular-devkit/core'
2 |
3 | export interface TestBuilderSchema extends JsonObject {
4 | outputPath?: string
5 | main?: string
6 | }
--------------------------------------------------------------------------------
/packages/nx-python/README.md:
--------------------------------------------------------------------------------
1 | # nx-python
2 |
3 | This library was generated with [Nx](https://nx.dev).
4 |
5 | ## Running unit tests
6 |
7 | Run `ng test nx-python` to execute the unit tests via [Jest](https://jestjs.io).
8 |
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/build/schema.d.ts:
--------------------------------------------------------------------------------
1 | import { JsonObject } from '@angular-devkit/core';
2 |
3 | export interface BuildBuilderSchema extends JsonObject {
4 | outputPath?: string
5 | main?: string
6 | }
7 |
--------------------------------------------------------------------------------
/packages/python-graph/README.md:
--------------------------------------------------------------------------------
1 | # nx-python
2 |
3 | This library was generated with [Nx](https://nx.dev).
4 |
5 | ## Running unit tests
6 |
7 | Run `ng test nx-python-project-graph` to execute the unit tests via [Jest](https://jestjs.io).
8 |
--------------------------------------------------------------------------------
/e2e/nx-python-e2e/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": ["**/*.spec.ts", "**/*.d.ts"]
9 | }
10 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/flask/src/name/api_doc.py.template:
--------------------------------------------------------------------------------
1 | """Index Doc module for the `<%= snakeName %>` service."""
2 | # -*- coding: utf-8 -*-
3 |
4 | INDEX_DOC = """
5 | /api/<%= snakeName %>/v1/
6 |
7 | """ # noqa: ignore=E501
8 |
--------------------------------------------------------------------------------
/e2e/nx-python-e2e/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "files": [],
4 | "include": [],
5 | "references": [
6 | {
7 | "path": "./tsconfig.e2e.json"
8 | },
9 | {
10 | "path": "./tsconfig.spec.json"
11 | }
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/packages/nx-python/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "files": [],
4 | "include": [],
5 | "references": [
6 | {
7 | "path": "./tsconfig.lib.json"
8 | },
9 | {
10 | "path": "./tsconfig.spec.json"
11 | }
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/packages/python-graph/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "files": [],
4 | "include": [],
5 | "references": [
6 | {
7 | "path": "./tsconfig.lib.json"
8 | },
9 | {
10 | "path": "./tsconfig.spec.json"
11 | }
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/tools/tsconfig.tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.base.json",
3 | "compilerOptions": {
4 | "outDir": "../dist/out-tsc/tools",
5 | "rootDir": ".",
6 | "module": "commonjs",
7 | "target": "es5",
8 | "types": ["node"]
9 | },
10 | "include": ["**/*.ts"]
11 | }
12 |
--------------------------------------------------------------------------------
/e2e/nx-python-e2e/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | name: 'nx-python-e2e',
3 | preset: '../../jest.config.js',
4 | globals: {
5 | 'ts-jest': {
6 | tsConfig: '/tsconfig.spec.json',
7 | },
8 | },
9 | coverageDirectory: '../../coverage/e2e/nx-python-e2e',
10 | };
11 |
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/build/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft-07/schema",
3 | "$id": "https://json-schema.org/draft-07/schema",
4 | "title": "Build builder",
5 | "description": "",
6 | "type": "object",
7 | "properties": {},
8 | "required": []
9 | }
10 |
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/lint/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft-07/schema",
3 | "$id": "https://json-schema.org/draft-07/schema",
4 | "title": "Build builder",
5 | "description": "",
6 | "type": "object",
7 | "properties": {},
8 | "required": []
9 | }
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/test/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft-07/schema",
3 | "$id": "https://json-schema.org/draft-07/schema",
4 | "title": "Build builder",
5 | "description": "",
6 | "type": "object",
7 | "properties": {},
8 | "required": []
9 | }
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/serve/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json-schema.org/draft-07/schema",
3 | "$id": "https://json-schema.org/draft-07/schema",
4 | "title": "Build builder",
5 | "description": "",
6 | "type": "object",
7 | "properties": {},
8 | "required": []
9 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'],
3 | testTimeout: 60000,
4 | transform: {
5 | '^.+\\.(ts|js|html)$': 'ts-jest',
6 | },
7 | resolver: '@nrwl/jest/plugins/resolver',
8 | moduleFileExtensions: ['ts', 'js', 'html'],
9 | coverageReporters: ['html'],
10 | };
11 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/schema.d.ts:
--------------------------------------------------------------------------------
1 | export type NxPythonTemplate = 'default' | 'django' | 'flask';
2 | export interface NxPythonSchematicSchema {
3 | name: string;
4 | tags?: string;
5 | description?: string;
6 | repoUrl?: string;
7 | directory?: string;
8 | template?: NxPythonTemplate;
9 | }
10 |
--------------------------------------------------------------------------------
/packages/nx-python/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "outDir": "../../dist/out-tsc",
6 | "declaration": true,
7 | "rootDir": ".",
8 | "types": ["node"]
9 | },
10 | "exclude": ["**/*.spec.ts"],
11 | "include": ["**/*.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/python-graph/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "outDir": "../../dist/out-tsc",
6 | "declaration": true,
7 | "rootDir": ".",
8 | "types": ["node"]
9 | },
10 | "exclude": ["**/*.spec.ts"],
11 | "include": ["**/*.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/flask/src/name/application.py.template:
--------------------------------------------------------------------------------
1 | """Main module for the `<%= snakeName %>` service."""
2 | import logging
3 | # TODO
4 |
5 | from <%= snakeName %> import api, app
6 |
7 | log = logging.getLogger("<%= snakeName %>")
8 |
9 | # TODO
10 |
11 | if __name__ == "__main__":
12 | app.run()
13 |
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/serve/schema.d.ts:
--------------------------------------------------------------------------------
1 | import { JsonObject } from '@angular-devkit/core'
2 | import { NxPythonTemplate } from '../../schematics/nx-python/schema';
3 |
4 | export interface ServeBuilderSchema extends JsonObject {
5 | main?: string
6 | outputPath?: string
7 | cwd?: string
8 | cmd?: string
9 | templateType?: NxPythonTemplate
10 | }
--------------------------------------------------------------------------------
/packages/nx-python/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "**/*.spec.ts",
10 | "**/*.spec.tsx",
11 | "**/*.spec.js",
12 | "**/*.spec.jsx",
13 | "**/*.d.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/packages/python-graph/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "**/*.spec.ts",
10 | "**/*.spec.tsx",
11 | "**/*.spec.js",
12 | "**/*.spec.jsx",
13 | "**/*.d.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/default/src/hello.py.template:
--------------------------------------------------------------------------------
1 | class HelloFactory:
2 | def __init__(self, **args):
3 | for key, value in args.items():
4 | setattr(self, key, 'Hello {}'.format(value))
5 |
6 |
7 | if __name__ == '__main__':
8 | hello = HelloFactory(application="<%= projectName %>", user="Human")
9 | print(hello.application)
10 |
--------------------------------------------------------------------------------
/packages/nx-python/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | name: 'nx-python',
3 | preset: '../../jest.config.js',
4 | globals: {
5 | 'ts-jest': {
6 | tsConfig: '/tsconfig.spec.json',
7 | },
8 | },
9 | transform: {
10 | '^.+\\.[tj]sx?$': 'ts-jest',
11 | },
12 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
13 | coverageDirectory: '../../coverage/packages/nx-python',
14 | };
15 |
--------------------------------------------------------------------------------
/packages/python-graph/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | name: 'nx-python-project-graph',
3 | preset: '../../jest.config.js',
4 | globals: {
5 | 'ts-jest': {
6 | tsConfig: '/tsconfig.spec.json',
7 | },
8 | },
9 | transform: {
10 | '^.+\\.[tj]sx?$': 'ts-jest',
11 | },
12 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
13 | coverageDirectory: '../../coverage/packages/nx-python-project-graph',
14 | };
15 |
--------------------------------------------------------------------------------
/packages/nx-python/collection.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../node_modules/@angular-devkit/schematics/collection-schema.json",
3 | "name": "nx-python",
4 | "version": "0.0.1",
5 | "schematics": {
6 | "nx-python": {
7 | "aliases": ["app"],
8 | "factory": "./src/schematics/nx-python/schematic",
9 | "schema": "./src/schematics/nx-python/schema.json",
10 | "description": "Creates a new Python Application"
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/default/src/test_hello.py.template:
--------------------------------------------------------------------------------
1 | from hello import HelloFactory
2 | import unittest
3 |
4 |
5 | class HelloTest(unittest.TestCase):
6 | def test_message(self):
7 | try:
8 | hello = HelloFactory(user="Human")
9 | self.assertEqual(hello.user, 'Hello Human')
10 | except Exception as e:
11 | print('Error: {}'.format(str(e)))
12 | self.assertTrue(False)
13 |
14 |
15 | if __name__ == '__main__':
16 | unittest.main()
17 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/django/src/asgi.py.template:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for <%= projectName %> project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'src.settings')
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/django/src/wsgi.py.template:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for <%= projectName %> project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', '<%= projectName %>.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/flask/wadl/name-wadl.xml.template:
--------------------------------------------------------------------------------
1 |
2 |
3 | ="API_URL" xmlns="http://wadl.dev.java.net/2009/02">
7 |
8 |
9 | <%= projectDescription %>
10 |
11 |
12 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/flask/requirements.txt:
--------------------------------------------------------------------------------
1 | aniso8601==2.0.0
2 | certifi==2017.11.5
3 | chardet==3.0.4
4 | click==6.7
5 | cryptography==3.0
6 | dnspython==1.16.0
7 | furl==2.1.0
8 | Flask==1.0.2
9 | Flask-RESTful==0.3.6
10 | Flask-Script==2.0.6
11 | gevent==1.2.2
12 | greenlet==0.4.12
13 | gunicorn==19.7.1
14 | idna==2.6
15 | itsdangerous==0.24
16 | Jinja2==2.10
17 | MarkupSafe==1.1.1
18 | mock==3.0.5
19 | python-dateutil
20 | PyJWT==1.7.1
21 | pytz==2017.3
22 | requests==2.18.4
23 | six==1.11.0
24 | urllib3==1.22
25 | voluptuous==0.11.5
26 | Werkzeug==0.14.1
27 | xmltodict==0.11.0
28 |
29 |
--------------------------------------------------------------------------------
/packages/python-graph/src/has-python-files.ts:
--------------------------------------------------------------------------------
1 | import recursive from 'recursive-readdir';
2 | import * as path from 'path';
3 |
4 | function notPythonFile(file, stats) {
5 | // `file` is the path to the file, and `stats` is an `fs.Stats`
6 | // object returned from `fs.lstat()`.
7 | return stats.isDirectory() || path.extname(file) !== '.py';
8 | }
9 |
10 | export const hasPythonFiles = (folder: string): Promise =>
11 | new Promise((resolve, reject) => {
12 | recursive(folder, [notPythonFile], (err, files) => {
13 | if (err) reject(err.message);
14 | resolve(files);
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/packages/nx-python/src/project-graph/has-python-files.ts:
--------------------------------------------------------------------------------
1 | import recursive from 'recursive-readdir';
2 | import * as path from 'path';
3 |
4 | function notPythonFile(file, stats) {
5 | // `file` is the path to the file, and `stats` is an `fs.Stats`
6 | // object returned from `fs.lstat()`.
7 | return stats.isDirectory() || path.extname(file) !== '.py';
8 | }
9 |
10 | export const hasPythonFiles = (folder: string): Promise =>
11 | new Promise((resolve, reject) => {
12 | recursive(folder, [notPythonFile], (err, files) => {
13 | if (err) reject(err.message);
14 | resolve(files);
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/tsconfig.base.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "rootDir": ".",
5 | "sourceMap": true,
6 | "declaration": false,
7 | "moduleResolution": "node",
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "importHelpers": true,
11 | "target": "es2015",
12 | "module": "esnext",
13 | "typeRoots": ["node_modules/@types"],
14 | "lib": ["es2017", "dom"],
15 | "skipLibCheck": true,
16 | "skipDefaultLibCheck": true,
17 | "baseUrl": ".",
18 | "paths": {
19 | "nx-python/nx-python": ["packages/nx-python/src/index.ts"]
20 | }
21 | },
22 | "exclude": ["node_modules", "tmp"]
23 | }
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | #github
4 | .github
5 |
6 | # compiled output
7 | /dist
8 | /tmp
9 | /out-tsc
10 |
11 | # dependencies
12 | /node_modules
13 |
14 | # IDEs and editors
15 | /.idea
16 | .project
17 | .classpath
18 | .c9/
19 | *.launch
20 | .settings/
21 | *.sublime-workspace
22 |
23 | # IDE - VSCode
24 | .vscode/*
25 | !.vscode/settings.json
26 | !.vscode/tasks.json
27 | !.vscode/launch.json
28 | !.vscode/extensions.json
29 |
30 | # misc
31 | /.sass-cache
32 | /connect.lock
33 | /coverage
34 | /libpeerconnection.log
35 | npm-debug.log
36 | yarn-error.log
37 | testem.log
38 | /typings
39 |
40 | # System Files
41 | .DS_Store
42 | Thumbs.db
43 |
--------------------------------------------------------------------------------
/packages/python-graph/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nx-python/nx-python-project-graph",
3 | "version": "1.0.1",
4 | "main": "src/index.js",
5 | "license": "MIT",
6 | "description": "This library was generated with [Nx](https://nx.dev).",
7 | "scripts": {
8 | "test": "nx test"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/codeonrocks/nx-python.git"
13 | },
14 | "keywords": [
15 | "nx",
16 | "python"
17 | ],
18 | "author": "Code On LLC",
19 | "bugs": {
20 | "url": "https://github.com/codeonrocks/nx-python/issues"
21 | },
22 | "homepage": "https://github.com/codeonrocks/nx-python#readme",
23 | "devDependencies": {
24 | "nxpm": "^1.15.0"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | * **Please check if the PR fulfills these requirements**
2 | - [ ] The commit message is clear and concise
3 | - [ ] Tests for the changes have been added (for bug fixes / features)
4 | - [ ] Docs/Readme have been added / updated (for bug fixes / features)
5 |
6 |
7 | * **What kind of change does this PR introduce?** (Bug fix, feature, docs update, ...)
8 |
9 |
10 |
11 | * **What is the current behavior?** (You can also link to an open issue here)
12 |
13 |
14 |
15 | * **What is the new behavior (if this is a feature change)?**
16 |
17 |
18 |
19 | * **Does this PR introduce a breaking change?** (What changes might users need to make in their application due to this PR?)
20 |
21 |
22 |
23 | * **Other information**:
24 |
--------------------------------------------------------------------------------
/packages/nx-python/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nx-python/nx-python",
3 | "version": "1.0.1",
4 | "main": "src/index.js",
5 | "schematics": "./collection.json",
6 | "builders": "./builders.json",
7 | "license": "MIT",
8 | "description": "This library was generated with [Nx](https://nx.dev).",
9 | "scripts": {
10 | "test": "nx test"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/codeonrocks/nx-python.git"
15 | },
16 | "keywords": [
17 | "nx",
18 | "python"
19 | ],
20 | "author": "Code On LLC",
21 | "bugs": {
22 | "url": "https://github.com/codeonrocks/nx-python/issues"
23 | },
24 | "homepage": "https://github.com/codeonrocks/nx-python#readme",
25 | "devDependencies": {
26 | "nxpm": "^1.15.0"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/django/manage.py.template:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | """Run administrative tasks."""
9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'src.settings')
10 | try:
11 | from django.core.management import execute_from_command_line
12 | except ImportError as exc:
13 | raise ImportError(
14 | "Couldn't import Django. Are you sure it's installed and "
15 | "available on your PYTHONPATH environment variable? Did you "
16 | "forget to activate a virtual environment?"
17 | ) from exc
18 | execute_from_command_line(sys.argv)
19 |
20 |
21 | if __name__ == '__main__':
22 | main()
23 |
--------------------------------------------------------------------------------
/nx.json:
--------------------------------------------------------------------------------
1 | {
2 | "npmScope": "nx-python",
3 | "affected": {
4 | "defaultBase": "master"
5 | },
6 | "implicitDependencies": {
7 | "workspace.json": "*",
8 | "package.json": {
9 | "dependencies": "*",
10 | "devDependencies": "*"
11 | },
12 | "tsconfig.base.json": "*",
13 | "tslint.json": "*",
14 | "nx.json": "*"
15 | },
16 | "tasksRunnerOptions": {
17 | "default": {
18 | "runner": "@nrwl/workspace/tasks-runners/default",
19 | "options": {
20 | "cacheableOperations": ["build", "lint", "test", "e2e"]
21 | }
22 | }
23 | },
24 | "projects": {
25 | "nx-python": {
26 | "tags": []
27 | },
28 | "nx-python-e2e": {
29 | "tags": [],
30 | "implicitDependencies": ["nx-python"]
31 | }
32 | },
33 | "workspaceLayout": {
34 | "appsDir": "e2e",
35 | "libsDir": "packages"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/packages/nx-python/builders.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../node_modules/@angular-devkit/architect/src/builders-schema.json",
3 | "builders": {
4 | "build": {
5 | "implementation": "./src/builders/build/builder",
6 | "schema": "./src/builders/build/schema.json",
7 | "description": "build builder"
8 | },
9 | "lint": {
10 | "implementation": "./src/builders/lint/builder",
11 | "schema": "./src/builders/lint/schema.json",
12 | "description": "lint builder"
13 | },
14 | "serve": {
15 | "implementation": "./src/builders/serve/builder",
16 | "schema": "./src/builders/serve/schema.json",
17 | "description": "serve builder"
18 | },
19 | "test": {
20 | "implementation": "./src/builders/test/builder",
21 | "schema": "./src/builders/test/schema.json",
22 | "description": "test builder"
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/django/src/urls.py.template:
--------------------------------------------------------------------------------
1 | """<%= projectName %> URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/3.1/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | from django.contrib import admin
17 | from django.urls import path
18 |
19 | urlpatterns = [
20 | path('admin/', admin.site.urls),
21 | ]
22 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/schematic.spec.ts:
--------------------------------------------------------------------------------
1 | import { Tree } from '@angular-devkit/schematics';
2 | import { SchematicTestRunner } from '@angular-devkit/schematics/testing';
3 | import { createEmptyWorkspace } from '@nrwl/workspace/testing';
4 | import { join } from 'path';
5 |
6 | import { NxPythonSchematicSchema } from './schema';
7 |
8 | describe('nx-python schematic', () => {
9 | let appTree: Tree;
10 | const options: NxPythonSchematicSchema = { name: 'test' };
11 |
12 | const testRunner = new SchematicTestRunner(
13 | '@nx-python/nx-python',
14 | join(__dirname, '../../../collection.json')
15 | );
16 |
17 | beforeEach(() => {
18 | appTree = createEmptyWorkspace(Tree.empty());
19 | });
20 |
21 | it('should run successfully', async () => {
22 | await expect(
23 | testRunner.runSchematicAsync('nx-python', options, appTree).toPromise()
24 | ).resolves.not.toThrowError();
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/serve/builder.ts:
--------------------------------------------------------------------------------
1 | import {
2 | BuilderContext,
3 | BuilderOutput,
4 | createBuilder,
5 | } from '@angular-devkit/architect';
6 |
7 | import { from, Observable } from 'rxjs';
8 | import { map } from 'rxjs/operators';
9 |
10 | import { getCliOptions, runPythonCommand } from '../../utils/py-utils';
11 |
12 | import { ServeBuilderSchema } from './schema';
13 |
14 | export function runBuilder(
15 | options: ServeBuilderSchema,
16 | context: BuilderContext
17 | ): Observable {
18 | const projMetadata = context.getProjectMetadata(context?.target?.project);
19 | return from(projMetadata).pipe(
20 | map((project) => {
21 | const mainFile = `${options.main}`;
22 |
23 | return runPythonCommand(
24 | context,
25 | 'serve',
26 | [mainFile],
27 | getCliOptions(options),
28 | project
29 | );
30 | })
31 | );
32 | }
33 |
34 | export default createBuilder(runBuilder);
35 |
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/test/builder.ts:
--------------------------------------------------------------------------------
1 | import {
2 | BuilderContext,
3 | BuilderOutput,
4 | createBuilder,
5 | } from '@angular-devkit/architect';
6 |
7 | import { from, Observable } from 'rxjs';
8 | import { map } from 'rxjs/operators';
9 |
10 | import { getCliOptions, runPythonCommand } from '../../utils/py-utils';
11 |
12 | import { TestBuilderSchema } from './schema';
13 |
14 | export function runBuilder(
15 | options: TestBuilderSchema,
16 | context: BuilderContext
17 | ): Observable {
18 | const projMetadata = context.getProjectMetadata(context?.target?.project);
19 | return from(projMetadata).pipe(
20 | map((project) => {
21 | const root = project.root;
22 | const sources = `${root}/src/*test*.py`;
23 |
24 | return runPythonCommand(
25 | context,
26 | 'test',
27 | [sources],
28 | getCliOptions(options),
29 | project
30 | );
31 | })
32 | );
33 | }
34 |
35 | export default createBuilder(runBuilder);
36 |
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/build/builder.ts:
--------------------------------------------------------------------------------
1 | import {
2 | BuilderContext,
3 | BuilderOutput,
4 | createBuilder,
5 | } from '@angular-devkit/architect';
6 |
7 | import { Observable, from } from 'rxjs';
8 | import { map } from 'rxjs/operators';
9 |
10 | import { getCliOptions, runPythonCommand } from '../../utils/py-utils';
11 |
12 | import { BuildBuilderSchema } from './schema';
13 |
14 | export function runBuilder(
15 | options: BuildBuilderSchema,
16 | context: BuilderContext
17 | ): Observable {
18 | const projMetadata = context.getProjectMetadata(context?.target?.project);
19 | return from(projMetadata).pipe(
20 | map((project) => {
21 | const mainFile = `${options.main}`;
22 | const output = `${options.outputPath}`;
23 | //Compile files using the native py_compile module
24 | return runPythonCommand(
25 | context,
26 | 'build',
27 | [mainFile],
28 | getCliOptions(options),
29 | project
30 | );
31 | })
32 | );
33 | }
34 |
35 | export default createBuilder(runBuilder);
36 |
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/lint/builder.ts:
--------------------------------------------------------------------------------
1 | import {
2 | BuilderContext,
3 | BuilderOutput,
4 | createBuilder,
5 | } from '@angular-devkit/architect';
6 |
7 | import { from, Observable } from 'rxjs';
8 | import { map } from 'rxjs/operators';
9 |
10 | import { getCliOptions, runPythonCommand } from '../../utils/py-utils';
11 |
12 | import { LintBuilderSchema } from './schema';
13 |
14 | export function runBuilder(
15 | options: LintBuilderSchema,
16 | context: BuilderContext
17 | ): Observable {
18 | const projMetadata = context.getProjectMetadata(context?.target?.project);
19 | return from(projMetadata).pipe(
20 | map((project) => {
21 | const root = project.root;
22 | // Route of python files
23 | const sources = `${root}/src/*.py`;
24 |
25 | // Executing linting using the flake8 module
26 | return runPythonCommand(
27 | context,
28 | 'lint',
29 | [sources],
30 | getCliOptions(options),
31 | project
32 | );
33 | })
34 | );
35 | }
36 |
37 | export default createBuilder(runBuilder);
38 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/flask/src/name/manage.py.template:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | manage.py is a thin wrapper that takes care of several things.
5 | It provides runserver and more.
6 | Please run `manage.py help` to see all options.
7 | """
8 |
9 | from flask_script import Manager, Server, Shell
10 |
11 | from <%= snakeName %>.application import app
12 | from <%= snakeName %> import settings
13 |
14 | manager = Manager(app)
15 |
16 |
17 | def make_shell_context():
18 | """Make a flask-script shell context containing app."""
19 | return dict(app=app)
20 |
21 |
22 | manager.add_command('shell', Shell(make_context=make_shell_context))
23 | manager.add_command(
24 | 'runserver', Server(host='0.0.0.0', port=7000, use_debugger=True)
25 | )
26 |
27 |
28 | def main():
29 | """Run development server."""
30 | if settings.TEST_MODE is True:
31 | from <%= snakeName %>.gabbi_utils import enable_test_mode
32 | enable_test_mode()
33 | manager.run(default_command='runserver')
34 |
35 |
36 | if __name__ == '__main__':
37 | main()
38 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/flask/Readme.md.template:
--------------------------------------------------------------------------------
1 | # <%= projectName %>
2 |
3 | <%= projectDescription %>
4 |
5 | ## Endpoints
6 |
7 | TODO
8 |
9 | ## Setup locally
10 |
11 | ### Create virtualenv and install dependencies
12 |
13 | ```bash
14 | virtualenv venv
15 | source venv/bin/activate
16 | # pip install ...
17 | pip install -r requirements.txt
18 | ```
19 |
20 | ### Setup env variable
21 |
22 | ```bash
23 | # TODO
24 | ```
25 |
26 | ### Run server
27 |
28 | Go to project root and run:
29 |
30 | ```bash
31 | export PYTHONPATH=`pwd`/src
32 | python src/manage.py
33 | ```
34 |
35 | It should start at `localhost:7000`
36 |
37 | ### API tests mode
38 |
39 | It assumes you have done previous steps.
40 | To run api test mode, it is required to set `mode` parameter to `gabbi`
41 | in test config (take a look at example_config.ini).
42 |
43 | #### Run tests
44 |
45 | 1. Run server
46 | 2. Activate virtualenv `source venv/bin/activate`
47 | 3. Install gabbi package `pip install gabbi`
48 | 4. Run tests using unittest
49 |
50 | ```bash
51 | gabbi-run localhost:7000 -- src/tests/gabbi/*
52 | ```
53 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Code ON LLC
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/flask/setup.py.template:
--------------------------------------------------------------------------------
1 | """Package configuration for `<%= snakeName %>`."""
2 | import os
3 |
4 | import setuptools
5 |
6 | here = os.path.abspath(os.path.dirname(__file__))
7 |
8 | setuptools.setup(
9 | name="<%= snakeName %>",
10 | version=open(os.path.join(here, 'VERSION')).read().strip(),
11 | url="<%= repoUrl %>",
12 | description='<%= description %>',
13 | long_description=open(os.path.join(here, 'README.md')).read(),
14 | classifiers=[
15 | 'Programming Language :: Python',
16 | 'Programming Language :: Python :: 3',
17 | 'Programming Language :: Python :: 3.6',
18 | ],
19 | packages=setuptools.find_packages('src', exclude=('tests',)),
20 | package_dir={'': 'src'},
21 | include_package_data=True,
22 | zip_safe=False,
23 |
24 | install_requires=[
25 | 'Flask',
26 | 'flask-restful',
27 | 'Flask-script',
28 | 'gevent',
29 | 'Werkzeug>=0.14',
30 | "pillow>=2.3.0,<3.0.0",
31 | ],
32 | extras_require={
33 | 'production': [
34 | 'gunicorn',
35 | ],
36 | }
37 | )
38 |
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 | * **I'm submitting a ...**
3 | - [ ] bug report
4 | - [ ] feature request
5 | - [ ] support request
6 |
7 | * **Do you want to request a *feature* or report a *bug*?**
8 |
9 |
10 |
11 | * **What is the current behavior?**
12 |
13 |
14 |
15 | * **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem** via
16 | https://plnkr.co or similar (you can use this template as a starting point: http://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5).
17 |
18 |
19 |
20 | * **What is the expected behavior?**
21 |
22 |
23 |
24 | * **What is the motivation / use case for changing the behavior?**
25 |
26 |
27 |
28 | * **Please tell us about your environment:**
29 |
30 | - Version:
31 | - Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
32 | - Language: [all | TypeScript X.X | ES6/7 | ES5 | Dart]
33 |
34 |
35 | * **Other information** (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)
36 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parser": "@typescript-eslint/parser",
4 | "parserOptions": {
5 | "ecmaVersion": 2018,
6 | "sourceType": "module",
7 | "project": "./tsconfig.base.json"
8 | },
9 | "ignorePatterns": ["**/*"],
10 | "plugins": ["@typescript-eslint", "@nrwl/nx"],
11 | "extends": [
12 | "eslint:recommended",
13 | "plugin:@typescript-eslint/eslint-recommended",
14 | "plugin:@typescript-eslint/recommended",
15 | "prettier",
16 | "prettier/@typescript-eslint"
17 | ],
18 | "rules": {
19 | "@typescript-eslint/explicit-member-accessibility": "off",
20 | "@typescript-eslint/explicit-function-return-type": "off",
21 | "@typescript-eslint/no-parameter-properties": "off",
22 | "@nrwl/nx/enforce-module-boundaries": [
23 | "error",
24 | {
25 | "enforceBuildableLibDependency": true,
26 | "allow": [],
27 | "depConstraints": [
28 | { "sourceTag": "*", "onlyDependOnLibsWithTags": ["*"] }
29 | ]
30 | }
31 | ]
32 | },
33 | "overrides": [
34 | {
35 | "files": ["*.tsx"],
36 | "rules": {
37 | "@typescript-eslint/no-unused-vars": "off"
38 | }
39 | }
40 | ]
41 | }
42 |
--------------------------------------------------------------------------------
/packages/nx-python/src/project-graph/index.ts:
--------------------------------------------------------------------------------
1 | import { hasPythonFiles } from './has-python-files';
2 | // import { BuilderContext } from '@angular-devkit/architect';
3 | import {
4 | ProjectGraphBuilder,
5 | ProjectGraph,
6 | ProjectGraphProcessorContext,
7 | } from '@nrwl/devkit';
8 |
9 | /**
10 | * Nx Project Graph plugin for go
11 | *
12 | * @param {import('@nrwl/devkit').ProjectGraph} graph
13 | * @param {import('@nrwl/devkit').ProjectGraphProcessorContext} context
14 | * @returns {import('@nrwl/devkit').ProjectGraph}
15 | */
16 | export const processProjectGraph = (
17 | graph: ProjectGraph,
18 | context: ProjectGraphProcessorContext
19 | ): ProjectGraph => {
20 | const builder = new ProjectGraphBuilder(graph);
21 |
22 | const projectNames = Object.keys(context.filesToProcess);
23 |
24 | const hasPythonCompiler = (project) => {
25 | const projectBuildOptions = project.targets['build'].options;
26 | return projectBuildOptions.compiler !== 'python';
27 | };
28 |
29 | const isPythonProject = (project) =>
30 | hasPythonCompiler(project) || hasPythonFiles(project.root);
31 |
32 | projectNames.map((projName) => {
33 | const project = context.workspace.projects[projName];
34 | if (!isPythonProject(project)) return;
35 | builder.addNode({
36 | name: projName,
37 | type: 'python',
38 | data: {
39 | files: projectNames[projName],
40 | },
41 | });
42 | });
43 | return builder.getUpdatedProjectGraph();
44 | };
45 |
--------------------------------------------------------------------------------
/packages/nx-python/src/utils/py-utils.ts:
--------------------------------------------------------------------------------
1 | import { JsonObject } from '@angular-devkit/core';
2 | import { BuilderContext } from '@angular-devkit/architect';
3 |
4 | import { execSync } from 'child_process';
5 |
6 | import { ServeBuilderSchema } from '../builders/serve/schema';
7 |
8 | import { CommandType } from '..';
9 | import { getExecuteCommand } from './command';
10 |
11 | export function runPythonCommand(
12 | context: BuilderContext,
13 | command: CommandType,
14 | params: string[],
15 | options: ServeBuilderSchema = {},
16 | projectMetadata: JsonObject
17 | ): { success: boolean } {
18 | // Take the parameters or set defaults
19 | const pythonRuntime = projectMetadata.python || 'python3';
20 | const cmd = options.cmd || pythonRuntime;
21 | const cwd = options.cwd || process.cwd();
22 |
23 | const execute = getExecuteCommand(
24 | cmd as string,
25 | command,
26 | params,
27 | projectMetadata
28 | );
29 | try {
30 | context.logger.info(`Executing command: ${execute}`);
31 | execSync(execute, { cwd, stdio: [0, 1, 2] });
32 | return { success: true };
33 | } catch (e) {
34 | context.logger.error(`Failed to execute command: ${execute}`, e);
35 | return { success: false };
36 | }
37 | }
38 |
39 | export function getCliOptions(options: ServeBuilderSchema): ServeBuilderSchema {
40 | const _options: ServeBuilderSchema = { ...options };
41 | if (options.cmd) {
42 | _options.cmd = options.cmd;
43 | }
44 | if (options.cwd) {
45 | _options.cwd = options.cwd;
46 | }
47 | return _options;
48 | }
49 |
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/lint/builder.spec.ts:
--------------------------------------------------------------------------------
1 | import { Architect } from '@angular-devkit/architect'
2 | import { TestingArchitectHost } from '@angular-devkit/architect/testing'
3 | import { schema } from '@angular-devkit/core'
4 | import { join } from 'path'
5 | import { LintBuilderSchema } from './schema'
6 |
7 | const options: LintBuilderSchema = {}
8 |
9 | describe('Command Runner Builder', () => {
10 | let architect: Architect
11 | let architectHost: TestingArchitectHost
12 |
13 | beforeEach(async () => {
14 | const registry = new schema.CoreSchemaRegistry()
15 | registry.addPostTransform(schema.transforms.addUndefinedDefaults)
16 |
17 | architectHost = new TestingArchitectHost('/root', '/root')
18 | architect = new Architect(architectHost, registry)
19 |
20 | // This will either take a Node package name, or a path to the directory
21 | // for the package.json file.
22 | await architectHost.addBuilderFromPackage(join(__dirname, '../../..'))
23 | })
24 |
25 | it('can run', async () => {
26 | // A "run" can have multiple outputs, and contains progress information.
27 | const run = await architect.scheduleBuilder('@nx-python/nx-python:lint', options)
28 | // The "result" member (of type BuilderOutput) is the next output.
29 | const output = await run.result
30 |
31 | // Stop the builder from running. This stops Architect from keeping
32 | // the builder-associated states in memory, since builders keep waiting
33 | // to be scheduled.
34 | await run.stop()
35 |
36 | // Expect that it succeeded.
37 | expect(output.success).toBe(true)
38 | })
39 | })
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/test/builder.spec.ts:
--------------------------------------------------------------------------------
1 | import { Architect } from '@angular-devkit/architect'
2 | import { TestingArchitectHost } from '@angular-devkit/architect/testing'
3 | import { schema } from '@angular-devkit/core'
4 | import { join } from 'path'
5 | import { TestBuilderSchema } from './schema'
6 |
7 | const options: TestBuilderSchema = {}
8 |
9 | describe('Command Runner Builder', () => {
10 | let architect: Architect
11 | let architectHost: TestingArchitectHost
12 |
13 | beforeEach(async () => {
14 | const registry = new schema.CoreSchemaRegistry()
15 | registry.addPostTransform(schema.transforms.addUndefinedDefaults)
16 |
17 | architectHost = new TestingArchitectHost('/root', '/root')
18 | architect = new Architect(architectHost, registry)
19 |
20 | // This will either take a Node package name, or a path to the directory
21 | // for the package.json file.
22 | await architectHost.addBuilderFromPackage(join(__dirname, '../../..'))
23 | })
24 |
25 | it('can run', async () => {
26 | // A "run" can have multiple outputs, and contains progress information.
27 | const run = await architect.scheduleBuilder('@nx-python/nx-python:test', options)
28 | // The "result" member (of type BuilderOutput) is the next output.
29 | const output = await run.result
30 |
31 | // Stop the builder from running. This stops Architect from keeping
32 | // the builder-associated states in memory, since builders keep waiting
33 | // to be scheduled.
34 | await run.stop()
35 |
36 | // Expect that it succeeded.
37 | expect(output.success).toBe(true)
38 | })
39 | })
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/serve/builder.spec.ts:
--------------------------------------------------------------------------------
1 | import { Architect } from '@angular-devkit/architect'
2 | import { TestingArchitectHost } from '@angular-devkit/architect/testing'
3 | import { schema } from '@angular-devkit/core'
4 | import { join } from 'path'
5 | import { ServeBuilderSchema } from './schema'
6 |
7 | const options: ServeBuilderSchema = {}
8 |
9 | describe('Command Runner Builder', () => {
10 | let architect: Architect
11 | let architectHost: TestingArchitectHost
12 |
13 | beforeEach(async () => {
14 | const registry = new schema.CoreSchemaRegistry()
15 | registry.addPostTransform(schema.transforms.addUndefinedDefaults)
16 |
17 | architectHost = new TestingArchitectHost('/root', '/root')
18 | architect = new Architect(architectHost, registry)
19 |
20 | // This will either take a Node package name, or a path to the directory
21 | // for the package.json file.
22 | await architectHost.addBuilderFromPackage(join(__dirname, '../../..'))
23 | })
24 |
25 | it('can run', async () => {
26 | // A "run" can have multiple outputs, and contains progress information.
27 | const run = await architect.scheduleBuilder('@nx-python/nx-python:serve', options)
28 | // The "result" member (of type BuilderOutput) is the next output.
29 |
30 | const output = await run.result
31 |
32 | // Stop the builder from running. This stops Architect from keeping
33 | // the builder-associated states in memory, since builders keep waiting
34 | // to be scheduled.
35 | await run.stop()
36 |
37 | // Expect that it succeeded.
38 | expect(output.success).toBe(true)
39 | })
40 | })
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/target-options.ts:
--------------------------------------------------------------------------------
1 | // TODO: remove `any` types later on
2 |
3 | import { join, normalize } from 'path';
4 |
5 | import { NxPythonTemplate } from './schema';
6 |
7 | interface IProject {
8 | root?: string;
9 | sourceRoot?: string;
10 | }
11 |
12 | export function getServeOptions(
13 | templateType: NxPythonTemplate,
14 | project: IProject
15 | ): any {
16 | return {
17 | main: getMainFilePath(templateType, project),
18 | templateType,
19 | };
20 | }
21 |
22 | export function getBuildOptions(
23 | templateType: NxPythonTemplate,
24 | project: IProject,
25 | options: any
26 | ): any {
27 | return {
28 | outputPath: join(normalize('dist'), options.projectRoot),
29 | main: getMainFilePath(templateType, project),
30 | templateType,
31 | };
32 | }
33 |
34 | export function getTestOptions(
35 | templateType: NxPythonTemplate,
36 | project: IProject
37 | ): any {
38 | return {
39 | main: getTestMainFilePath(templateType, project),
40 | templateType,
41 | };
42 | }
43 |
44 | export function getLintOptions(
45 | templateType: NxPythonTemplate,
46 | project: IProject
47 | ): any {
48 | return {
49 | main: getMainFilePath(templateType, project),
50 | templateType,
51 | };
52 | }
53 |
54 | function getTestMainFilePath(template: NxPythonTemplate, project): string {
55 | return join(project.sourceRoot, 'test_hello.py');
56 | }
57 |
58 | function getMainFilePath(template: NxPythonTemplate, project): string {
59 | if (template === 'django' || template === 'flask') {
60 | return join(project.root, 'manage.py');
61 | }
62 | return join(project.sourceRoot, 'hello.py');
63 | }
64 |
--------------------------------------------------------------------------------
/packages/nx-python/src/builders/build/builder.spec.ts:
--------------------------------------------------------------------------------
1 | import { Architect } from '@angular-devkit/architect';
2 | import { TestingArchitectHost } from '@angular-devkit/architect/testing';
3 | import { schema } from '@angular-devkit/core';
4 | import { join } from 'path';
5 | import { BuildBuilderSchema } from './schema';
6 |
7 | const options: BuildBuilderSchema = {}
8 |
9 | describe('Command Runner Builder', () => {
10 | let architect: Architect;
11 | let architectHost: TestingArchitectHost;
12 |
13 | beforeEach(async () => {
14 | const registry = new schema.CoreSchemaRegistry();
15 | registry.addPostTransform(schema.transforms.addUndefinedDefaults);
16 |
17 | architectHost = new TestingArchitectHost('/root', '/root');
18 | architect = new Architect(architectHost, registry);
19 |
20 | // This will either take a Node package name, or a path to the directory
21 | // for the package.json file.
22 | await architectHost.addBuilderFromPackage(join(__dirname, '../../..'));
23 | });
24 |
25 | it('can run', async () => {
26 | // A "run" can have multiple outputs, and contains progress information.
27 | const run = await architect.scheduleBuilder(
28 | '@nx-python/nx-python:build',
29 | options
30 | );
31 | // The "result" member (of type BuilderOutput) is the next output.
32 | const output = await run.result;
33 |
34 | // Stop the builder from running. This stops Architect from keeping
35 | // the builder-associated states in memory, since builders keep waiting
36 | // to be scheduled.
37 | await run.stop();
38 |
39 | // Expect that it succeeded.
40 | expect(output.success).toBe(true);
41 | });
42 | });
43 |
--------------------------------------------------------------------------------
/packages/nx-python/src/utils/command.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-explicit-any */
2 | import { JsonObject } from '@angular-devkit/core';
3 |
4 | import { cosmiconfigSync } from 'cosmiconfig';
5 |
6 | import { CommandType } from '..';
7 |
8 | const testers = {
9 | pytest: '-m pytest',
10 | unittest: '-m unittest discover -s ./ -p',
11 | };
12 |
13 | const linters = {
14 | pylint: '-m pylint',
15 | flake8: '-m flake8',
16 | mypy: '-m mypy',
17 | };
18 |
19 | const builders = {
20 | default: '-m py_compile',
21 | numba: '-m numba',
22 | cython: 'build_ext --inplace',
23 | };
24 |
25 | const defaults: any = {
26 | python: {
27 | serve: ' ',
28 | build: builders.default,
29 | lint: linters.flake8,
30 | test: testers.unittest,
31 | },
32 | };
33 |
34 | defaults.django = {
35 | ...defaults.python,
36 | serve: 'runserver',
37 | };
38 |
39 | defaults.flask = {
40 | ...defaults.python,
41 | pyServe: 'flask run',
42 | };
43 |
44 | export function getExecuteCommand(
45 | cmd: string,
46 | command: CommandType,
47 | params: string[],
48 | projectMetadata: JsonObject
49 | ): string {
50 | let mutate_command = '';
51 | const explorerSync = cosmiconfigSync('nx-python');
52 | const { config } = explorerSync.search('commands');
53 | const projCommands = (projectMetadata.commands as any) || {};
54 | const commandsObj = {
55 | ...config,
56 | ...projCommands,
57 | };
58 | const projectType: string = (projectMetadata.projectType as any) || 'python';
59 | const pyOpts = {
60 | ...defaults[projectType],
61 | ...commandsObj,
62 | };
63 |
64 | // Create the command to execute
65 | mutate_command = pyOpts[command] || command;
66 | return `${cmd} ${mutate_command} ${params.join(' ')}`;
67 | }
68 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/draft-07/schema",
3 | "id": "NxPython",
4 | "title": "",
5 | "type": "object",
6 | "properties": {
7 | "name": {
8 | "type": "string",
9 | "description": "",
10 | "$default": {
11 | "$source": "argv",
12 | "index": 0
13 | },
14 | "x-prompt": "What name would you like to use?"
15 | },
16 | "tags": {
17 | "type": "string",
18 | "description": "Add tags to the project (used for linting)",
19 | "alias": "t"
20 | },
21 | "description": {
22 | "type": "string",
23 | "description": "Project description",
24 | "alias": "d"
25 | },
26 | "repoUrl": {
27 | "type": "string",
28 | "description": "Repository url",
29 | "alias": "r"
30 | },
31 | "directory": {
32 | "type": "string",
33 | "description": "A directory where the project is placed",
34 | "alias": "d"
35 | },
36 | "template": {
37 | "type": "string",
38 | "alias": "f",
39 | "default": "default",
40 | "x-prompt": {
41 | "message": "Which python framework would you like to use for the application?",
42 | "type": "list",
43 | "items": [
44 | {
45 | "value": "default",
46 | "label": "(default) [ https://www.python.org/ ]"
47 | },
48 | {
49 | "value": "django",
50 | "label": "django [ https://www.djangoproject.com/ ]"
51 | },
52 | {
53 | "value": "flask",
54 | "label": "Flask [ https://pypi.org/project/Flask/ ]"
55 | }
56 | ]
57 | }
58 | }
59 | },
60 | "required": [
61 | "name"
62 | ]
63 | }
64 |
--------------------------------------------------------------------------------
/packages/python-graph/src/index.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable @typescript-eslint/no-explicit-any */
2 | import {
3 | ProjectGraphBuilder,
4 | ProjectGraph,
5 | ProjectGraphProcessorContext,
6 | } from '@nrwl/devkit';
7 |
8 | import * as path from 'path';
9 |
10 | import { hasPythonFiles } from './has-python-files';
11 |
12 | /**
13 | * Nx Project Graph plugin for go
14 | *
15 | * @param {import('@nrwl/devkit').ProjectGraph} graph
16 | * @param {import('@nrwl/devkit').ProjectGraphProcessorContext} context
17 | * @returns {import('@nrwl/devkit').ProjectGraph}
18 | */
19 | export const processProjectGraph = (
20 | graph: ProjectGraph,
21 | context: ProjectGraphProcessorContext
22 | ): ProjectGraph => {
23 | const builder = new ProjectGraphBuilder(graph);
24 |
25 | const projectNames = Object.keys(context.filesToProcess);
26 |
27 | const hasPythonCompiler = (project) => {
28 | const projectBuildOptions = project.targets['build'].options;
29 | return projectBuildOptions.compiler !== 'python';
30 | };
31 |
32 | const isPythonProject = (project) =>
33 | hasPythonCompiler(project) || hasPythonFiles(project.root);
34 |
35 | const pythonFileExtensions = [
36 | '.py',
37 | '.pyw',
38 | '.pyi',
39 | '.json',
40 | '.toml',
41 | '.xml',
42 | '.yaml',
43 | '.yml',
44 | ];
45 | const isPythonFile = (file) =>
46 | pythonFileExtensions.includes(path.extname(file));
47 |
48 | const filterPythonFiles = (files: string[]) => files.filter(isPythonFile);
49 |
50 | projectNames.map((projName) => {
51 | const project = context.workspace.projects[projName];
52 | if (!isPythonProject(project)) return;
53 | const projFiles = projectNames[projName];
54 | const pythonFiles = filterPythonFiles(projFiles);
55 | builder.addNode({
56 | name: projName,
57 | type: 'python',
58 | data: {
59 | files: pythonFiles,
60 | },
61 | });
62 | });
63 | return builder.getUpdatedProjectGraph();
64 | };
65 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/flask/wadl/wadl.xsl.template:
--------------------------------------------------------------------------------
1 |
2 |
31 |
38 |
39 |
--------------------------------------------------------------------------------
/e2e/nx-python-e2e/tests/nx-python.test.ts:
--------------------------------------------------------------------------------
1 | import {
2 | checkFilesExist,
3 | ensureNxProject,
4 | readJson,
5 | runNxCommandAsync,
6 | uniq,
7 | } from '@nrwl/nx-plugin/testing';
8 | describe('nx-python e2e', () => {
9 | it('should create nx-python', async (done) => {
10 | const plugin = uniq('nx-python');
11 | ensureNxProject('@nx-python/nx-python', 'dist/packages/nx-python');
12 | await runNxCommandAsync(`generate @nx-python/nx-python:app ${plugin}`);
13 |
14 | const resultBuild = await runNxCommandAsync(`build ${plugin}`)
15 | expect(resultBuild.stdout).toContain(`Executing command: python3 -m py_compile`)
16 |
17 | const resultLint = await runNxCommandAsync(`lint ${plugin}`)
18 | expect(resultLint.stdout).toContain(`Executing command: python3 -m flake8 apps/${plugin}/src/*.py`)
19 |
20 | const resultServe = await runNxCommandAsync(`serve ${plugin}`)
21 | expect(resultServe.stdout).toContain(`Executing command: python3`)
22 |
23 | const resultTest = await runNxCommandAsync(`test ${plugin}`)
24 | expect(resultTest.stdout).toContain(`Executing command: python3 -m unittest discover -s ./ -p apps/${plugin}/src/*test*.py`)
25 |
26 | done();
27 | });
28 |
29 | describe('--directory', () => {
30 | it('should create src in the specified directory', async (done) => {
31 | const plugin = uniq('nx-python');
32 | ensureNxProject('@nx-python/nx-python', 'dist/packages/nx-python');
33 | await runNxCommandAsync(
34 | `generate @nx-python/nx-python:app ${plugin} --directory subdir`
35 | );
36 | expect(() =>
37 | checkFilesExist(`apps/subdir/${plugin}/src/hello.py`)
38 | ).not.toThrow();
39 | done();
40 | });
41 | });
42 |
43 | describe('--tags', () => {
44 | it('should add tags to nx.json', async (done) => {
45 | const plugin = uniq('nx-python');
46 | ensureNxProject('@nx-python/nx-python', 'dist/packages/nx-python');
47 | await runNxCommandAsync(
48 | `generate @nx-python/nx-python:app ${plugin} --tags e2etag,e2ePackage`
49 | );
50 | const nxJson = readJson('nx.json');
51 | expect(nxJson.projects[plugin].tags).toEqual(['e2etag', 'e2ePackage']);
52 | done();
53 | });
54 | });
55 | });
56 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@nx-python/nx-python",
3 | "version": "1.0.2",
4 | "license": "MIT",
5 | "scripts": {
6 | "nx": "nx",
7 | "start": "nx serve",
8 | "build": "nx build",
9 | "test": "nx test",
10 | "lint": "nx workspace-lint && nx lint",
11 | "e2e": "nx e2e",
12 | "affected:apps": "nx affected:apps",
13 | "affected:libs": "nx affected:libs",
14 | "affected:build": "nx affected:build",
15 | "affected:e2e": "nx affected:e2e",
16 | "affected:test": "nx affected:test",
17 | "affected:lint": "nx affected:lint",
18 | "affected:dep-graph": "nx affected:dep-graph",
19 | "affected": "nx affected",
20 | "format": "nx format:write",
21 | "format:write": "nx format:write",
22 | "format:check": "nx format:check",
23 | "update": "nx migrate latest",
24 | "workspace-schematic": "nx workspace-schematic",
25 | "dep-graph": "nx dep-graph",
26 | "help": "nx help"
27 | },
28 | "private": false,
29 | "dependencies": {
30 | "@nrwl/devkit": "^12.9.0",
31 | "change-case": "^4.1.2",
32 | "cosmiconfig": "^7.0.1",
33 | "global": "^4.4.0",
34 | "recursive-readdir": "^2.2.2"
35 | },
36 | "devDependencies": {
37 | "@nrwl/eslint-plugin-nx": "10.4.4",
38 | "@nrwl/jest": "10.4.4",
39 | "@nrwl/nx-plugin": "10.4.4",
40 | "@nrwl/workspace": "10.4.4",
41 | "@types/jest": "26.0.8",
42 | "@types/node": "~8.9.4",
43 | "@typescript-eslint/eslint-plugin": "4.3.0",
44 | "@typescript-eslint/parser": "4.3.0",
45 | "dotenv": "6.2.0",
46 | "eslint": "6.8.0",
47 | "eslint-config-prettier": "6.0.0",
48 | "jest": "26.2.2",
49 | "nxpm": "^1.15.0",
50 | "prettier": "2.1.2",
51 | "ts-jest": "26.4.0",
52 | "ts-node": "~7.0.0",
53 | "tslint": "~6.0.0",
54 | "typescript": "4.0.5"
55 | },
56 | "description": "This project was generated using [Nx](https://nx.dev).",
57 | "main": "nx.json",
58 | "repository": {
59 | "type": "git",
60 | "url": "git+https://github.com/codeonrocks/nx-python.git"
61 | },
62 | "keywords": [
63 | "nx",
64 | "python"
65 | ],
66 | "author": "Code ON LLC",
67 | "bugs": {
68 | "url": "https://github.com/codeonrocks/nx-python/issues"
69 | },
70 | "homepage": "https://github.com/codeonrocks/nx-python#readme"
71 | }
72 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/flask/src/name/__init__.py.template:
--------------------------------------------------------------------------------
1 | """Module for the `<%= snakeName %>` service."""
2 | # -*- coding: utf-8 -*-
3 |
4 | import logging.config
5 | import syslog
6 | import traceback
7 |
8 | from flask import Flask
9 | from flask_restful import Api
10 | from werkzeug.exceptions import NotFound, Unauthorized
11 | from werkzeug.routing import RequestRedirect
12 |
13 | from <%= snakeName %> import settings
14 |
15 |
16 | ###########################
17 | # Setup and configuration #
18 | ###########################
19 | app = Flask(__name__)
20 | app.config['ERROR_404_HELP'] = False
21 | app.config['PROPAGATE_EXCEPTIONS'] = True
22 | api = Api(app)
23 |
24 |
25 | logging.config.dictConfig({
26 | 'version': 1,
27 | 'formatters': {
28 | 'default': {
29 | 'format': (
30 | '[%(levelname)s] %(asctime)s - %(name)s - lineno: %(lineno)d - %(message)s' # noqa: E501
31 | ),
32 | 'datefmt': '%d/%b/%Y:%H:%M:%S %z',
33 | }
34 | },
35 | 'handlers': {
36 | 'syslog': {
37 | 'class': 'logging.handlers.SysLogHandler',
38 | 'formatter': 'default',
39 | 'address':
40 | '/var/run/syslog' if getattr(settings, 'DEV_MODE', False)
41 | else '/dev/log',
42 | 'facility': syslog.LOG_LOCAL1,
43 | }
44 | },
45 | 'loggers': {
46 | '<%= snakeName %>': {
47 | 'handlers': ['syslog'],
48 | },
49 | }
50 | })
51 |
52 |
53 | @app.errorhandler(Exception)
54 | def unhandled_server_error(e):
55 | """Unhandled error handler."""
56 | if isinstance(e, (NotFound, RequestRedirect, Unauthorized)):
57 | return e
58 | err_trace = traceback.format_tb(e.__traceback__)
59 | syslog.syslog(
60 | syslog.LOG_ERR,
61 | "## [<%= snakeName %>] UNHANDLED ERROR TRACEBACK: START ##")
62 | syslog.syslog(
63 | syslog.LOG_ERR,
64 | "Error type: {err_type}, cause: {err_msg}".format(
65 | err_type=str(type(e)), err_msg=str(e))
66 | )
67 | syslog.syslog(syslog.LOG_ERR, "-- Traceback:")
68 | for line in err_trace:
69 | syslog.syslog(syslog.LOG_ERR, line)
70 | syslog.syslog(
71 | syslog.LOG_ERR,
72 | "## [<%= snakeName %>] UNHANDLED ERROR TRACEBACK: END ##")
73 | return "<%= snakeName %> Internal Server Error", 500
74 |
--------------------------------------------------------------------------------
/migrations.json:
--------------------------------------------------------------------------------
1 | {
2 | "migrations": [
3 | {
4 | "version": "10.1.0-beta.0",
5 | "description": "Migrate .eslintrc files to use tsconfig with a wildcard",
6 | "factory": "./src/migrations/update-10-1-0/migrate-eslintrc-tsconfig-wildcard",
7 | "package": "@nrwl/workspace",
8 | "name": "migrate-eslintrc-tsconfig-wildcard"
9 | },
10 | {
11 | "version": "10.3.0-beta.0",
12 | "description": "Add @nrwl/cli as dependency",
13 | "factory": "./src/migrations/update-10-3-0/add-cli-dependency",
14 | "package": "@nrwl/workspace",
15 | "name": "add-cli-dependency"
16 | },
17 | {
18 | "version": "10.3.0-beta.0",
19 | "description": "Update typescript to v4",
20 | "factory": "./src/migrations/update-10-3-0/update-typescript",
21 | "package": "@nrwl/workspace",
22 | "name": "update-10-3-0"
23 | },
24 | {
25 | "version": "10.3.0-beta.1",
26 | "description": "Adds .vscode/extensions.json to a workspace",
27 | "factory": "./src/migrations/update-10-3-0/add-vscode-extensions",
28 | "package": "@nrwl/workspace",
29 | "name": "add-vscode-extensions"
30 | },
31 | {
32 | "version": "10.3.0-beta.0",
33 | "description": "Adds `buildableProjectDepsInPackageJsonType` for web and angular package builders",
34 | "factory": "./src/migrations/update-10-3-0/add-buildable-project-deps-in-package-json-type",
35 | "package": "@nrwl/workspace",
36 | "name": "add-buildable-project-deps-in-package-json-type"
37 | },
38 | {
39 | "version": "10.4.0-beta.5",
40 | "description": "Add an explicit dependency on @nrwl/tao",
41 | "factory": "./src/migrations/update-10-4-0/add-explicit-dep-on-tao",
42 | "package": "@nrwl/workspace",
43 | "name": "add-explicit-dep-on-tao"
44 | },
45 | {
46 | "version": "10.1.0-beta.4",
47 | "description": "Update jest to v26",
48 | "factory": "./src/migrations/update-10-1-0/update-10-1-0",
49 | "package": "@nrwl/jest",
50 | "name": "update-10.1.0"
51 | },
52 | {
53 | "version": "10.2.0",
54 | "description": "Remove deprecated jest builder options",
55 | "factory": "./src/migrations/update-10-2-0/update-10-2-0",
56 | "package": "@nrwl/jest",
57 | "name": "update-10.2.0"
58 | },
59 | {
60 | "version": "10.3.0-beta.1",
61 | "description": "Adds all jest projects into the root jest config",
62 | "factory": "./src/migrations/update-10-3-0/update-projects-property",
63 | "package": "@nrwl/jest",
64 | "name": "update-projects-property"
65 | },
66 | {
67 | "version": "10.3.1-beta.1",
68 | "description": "Fix ts-jest migration",
69 | "factory": "./src/migrations/update-10-3-0/update-ts-jest",
70 | "package": "@nrwl/jest",
71 | "name": "update-ts-jest"
72 | },
73 | {
74 | "version": "10.3.0-beta.1",
75 | "description": "Adds a jest extension to the recommended extensions for vscode",
76 | "factory": "./src/migrations/update-10-3-0/add-jest-extension",
77 | "package": "@nrwl/jest",
78 | "name": "add-jest-extension"
79 | }
80 | ]
81 | }
--------------------------------------------------------------------------------
/packages/nx-python/READM.md:
--------------------------------------------------------------------------------
1 | # 🐍 NxPy: Nx Python plugin
2 |
3 | This project was generated using [Nx](https://nx.dev).
4 |
5 |
6 |
7 |
8 |
9 |
10 | The `nx-python` plugin allows users to create a basic python application using `nx` commands. To add the plugin to your project, just follow these steps:
11 |
12 | ## Getting started
13 |
14 | ### Create a Nx Workspace
15 |
16 | Before installing the `nx-python` plugin, it is required to have a pre-configured Nx Workspace . If you don't, then proceed to create a new one executing the following command:
17 |
18 | ```
19 | npx create-nx-workspace python-workspace --preset=empty --cli=nx --nx-cloud true
20 | cd python-workspace
21 | ```
22 |
23 | ### Install the `nx-python` plugin
24 |
25 | ```
26 | yarn add -D @nx-python/nx-python
27 | ```
28 |
29 | ### Adding an application to our workspace
30 |
31 | To create a new python application based on this plugin, please execute the following command:
32 |
33 | ```
34 | nx g @nx-python/nx-python:app
35 | ```
36 |
37 | **Note:** Replace `` with the name of your new application
38 |
39 | ## Usage
40 |
41 | After creating the `` application using the `nx-python` plugin. We can execute the build, lint, test and serve `nx commands` on this new application. Output will be stored on `dist//` directory.
42 |
43 | ### Building the app
44 |
45 | The `build` command is going to compile all the python files inside `` directory, using the `py_compile` native module.
46 |
47 | ```
48 | nx build
49 | ```
50 |
51 | More information here: [py_compile](https://docs.python.org/3/library/py_compile.html)
52 |
53 | ### Linting the application
54 |
55 | Unfortunately Python doesn't have a native linting module(yet!). `nx-python` uses the `Flake8` module to lint your application. It is required that you install this module beforehand. More info here: [Flake8](https://flake8.pycqa.org/en/latest/)
56 |
57 | ```
58 | pip install Flake8
59 | ```
60 |
61 | After that you can perform the lint process with:
62 |
63 | ```
64 | nx lint
65 | ```
66 |
67 | ### Serving the application
68 |
69 | This is going to execute the main file in your python application.
70 |
71 | ```
72 | nx serve
73 | ```
74 |
75 | ### Testing your application
76 |
77 | The `test` command is going to execute all the test units inside your python app. You can add new test unit files if you want, but there are two requirements that you must meet:
78 |
79 | - The filename must include the prefix `test`
80 | - Because we are using the native `unittest` python module to make our tests, you are going to create the tests based on this approach. More info here: [unittest](https://docs.python.org/3/library/unittest.html)
81 |
82 | To test your python app, execute the command:
83 |
84 | ```
85 | nx test
86 | ```
87 | ## Contributing
88 |
89 | 🐍 All contributions are welcome. Make sure you follow the [code of conduct](CODE_OF_CONDUCT.md) in this repository.
90 |
91 | ## MIT License
92 |
93 | Made with 💜 by [Code ON](https://codeon.rocks) | [Melvin Vega](https://github.com/melveg) & [Diana Rodriguez](https://github.com/sponsors/alphacentauri82)
94 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at support@nexmo.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/files/django/src/settings.py.template:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for <%= projectName %> project.
3 |
4 | Generated by 'django-admin startproject' using Django 3.1.3.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.1/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/3.1/ref/settings/
11 | """
12 |
13 | from pathlib import Path
14 |
15 | # Build paths inside the project like this: BASE_DIR / 'subdir'.
16 | BASE_DIR = Path(__file__).resolve().parent.parent
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = 'xqel9-rtlgqhv$4aj((s=ql)j5vkbibxd2h71ju9bnx2&q^fz5'
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = []
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | 'django.contrib.admin',
35 | 'django.contrib.auth',
36 | 'django.contrib.contenttypes',
37 | 'django.contrib.sessions',
38 | 'django.contrib.messages',
39 | 'django.contrib.staticfiles',
40 | ]
41 |
42 | MIDDLEWARE = [
43 | 'django.middleware.security.SecurityMiddleware',
44 | 'django.contrib.sessions.middleware.SessionMiddleware',
45 | 'django.middleware.common.CommonMiddleware',
46 | 'django.middleware.csrf.CsrfViewMiddleware',
47 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
48 | 'django.contrib.messages.middleware.MessageMiddleware',
49 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
50 | ]
51 |
52 | ROOT_URLCONF = 'src.urls'
53 |
54 | TEMPLATES = [
55 | {
56 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
57 | 'DIRS': [],
58 | 'APP_DIRS': True,
59 | 'OPTIONS': {
60 | 'context_processors': [
61 | 'django.template.context_processors.debug',
62 | 'django.template.context_processors.request',
63 | 'django.contrib.auth.context_processors.auth',
64 | 'django.contrib.messages.context_processors.messages',
65 | ],
66 | },
67 | },
68 | ]
69 |
70 | WSGI_APPLICATION = 'src.wsgi.application'
71 |
72 |
73 | # Database
74 | # https://docs.djangoproject.com/en/3.1/ref/settings/#databases
75 |
76 | DATABASES = {
77 | 'default': {
78 | 'ENGINE': 'django.db.backends.sqlite3',
79 | 'NAME': BASE_DIR / 'db.sqlite3',
80 | }
81 | }
82 |
83 |
84 | # Password validation
85 | # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
86 |
87 | AUTH_PASSWORD_VALIDATORS = [
88 | {
89 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
90 | },
91 | {
92 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
93 | },
94 | {
95 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
96 | },
97 | {
98 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
99 | },
100 | ]
101 |
102 |
103 | # Internationalization
104 | # https://docs.djangoproject.com/en/3.1/topics/i18n/
105 |
106 | LANGUAGE_CODE = 'en-us'
107 |
108 | TIME_ZONE = 'UTC'
109 |
110 | USE_I18N = True
111 |
112 | USE_L10N = True
113 |
114 | USE_TZ = True
115 |
116 |
117 | # Static files (CSS, JavaScript, Images)
118 | # https://docs.djangoproject.com/en/3.1/howto/static-files/
119 |
120 | STATIC_URL = '/static/'
121 |
--------------------------------------------------------------------------------
/workspace.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "projects": {
4 | "nx-python": {
5 | "root": "packages/nx-python",
6 | "sourceRoot": "packages/nx-python/src",
7 | "projectType": "library",
8 | "schematics": {},
9 | "architect": {
10 | "lint": {
11 | "builder": "@nrwl/linter:lint",
12 | "options": {
13 | "linter": "eslint",
14 | "tsConfig": [
15 | "packages/nx-python/tsconfig.lib.json",
16 | "packages/nx-python/tsconfig.spec.json"
17 | ],
18 | "exclude": ["**/node_modules/**", "!packages/nx-python/**/*"]
19 | }
20 | },
21 | "test": {
22 | "builder": "@nrwl/jest:jest",
23 | "options": {
24 | "jestConfig": "packages/nx-python/jest.config.js",
25 | "tsConfig": "packages/nx-python/tsconfig.spec.json",
26 | "passWithNoTests": true
27 | }
28 | },
29 | "build": {
30 | "builder": "@nrwl/node:package",
31 | "options": {
32 | "outputPath": "dist/packages/nx-python",
33 | "tsConfig": "packages/nx-python/tsconfig.lib.json",
34 | "packageJson": "packages/nx-python/package.json",
35 | "main": "packages/nx-python/src/index.ts",
36 | "assets": [
37 | "packages/nx-python/*.md",
38 | {
39 | "input": "./packages/nx-python/src",
40 | "glob": "**/*.!(ts)",
41 | "output": "./src"
42 | },
43 | {
44 | "input": "./packages/nx-python",
45 | "glob": "collection.json",
46 | "output": "."
47 | },
48 | {
49 | "input": "./packages/nx-python",
50 | "glob": "builders.json",
51 | "output": "."
52 | }
53 | ]
54 | }
55 | }
56 | }
57 | },
58 | "nx-python-e2e": {
59 | "projectType": "application",
60 | "root": "e2e/nx-python-e2e",
61 | "sourceRoot": "e2e/nx-python-e2e/src",
62 | "architect": {
63 | "e2e": {
64 | "builder": "@nrwl/nx-plugin:e2e",
65 | "options": {
66 | "target": "nx-python:build",
67 | "npmPackageName": "@nx-python/nx-python",
68 | "pluginOutputPath": "dist/packages/nx-python",
69 | "jestConfig": "e2e/nx-python-e2e/jest.config.js",
70 | "tsSpecConfig": "e2e/nx-python-e2e/tsconfig.spec.json"
71 | }
72 | }
73 | }
74 | }
75 | },
76 | "cli": {
77 | "defaultCollection": "@nrwl/workspace"
78 | },
79 | "schematics": {
80 | "@nrwl/workspace": {
81 | "library": {
82 | "linter": "eslint"
83 | }
84 | },
85 | "@nrwl/cypress": {
86 | "cypress-project": {
87 | "linter": "eslint"
88 | }
89 | },
90 | "@nrwl/react": {
91 | "application": {
92 | "linter": "eslint"
93 | },
94 | "library": {
95 | "linter": "eslint"
96 | },
97 | "storybook-configuration": {
98 | "linter": "eslint"
99 | }
100 | },
101 | "@nrwl/next": {
102 | "application": {
103 | "linter": "eslint"
104 | }
105 | },
106 | "@nrwl/web": {
107 | "application": {
108 | "linter": "eslint"
109 | }
110 | },
111 | "@nrwl/node": {
112 | "application": {
113 | "linter": "eslint"
114 | },
115 | "library": {
116 | "linter": "eslint"
117 | }
118 | },
119 | "@nrwl/nx-plugin": {
120 | "plugin": {
121 | "linter": "eslint"
122 | }
123 | },
124 | "@nrwl/nest": {
125 | "application": {
126 | "linter": "eslint"
127 | }
128 | },
129 | "@nrwl/express": {
130 | "application": {
131 | "linter": "eslint"
132 | },
133 | "library": {
134 | "linter": "eslint"
135 | }
136 | }
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/packages/nx-python/src/schematics/nx-python/schematic.ts:
--------------------------------------------------------------------------------
1 | import {
2 | apply,
3 | applyTemplates,
4 | chain,
5 | mergeWith,
6 | move,
7 | Rule,
8 | url,
9 | } from '@angular-devkit/schematics';
10 |
11 | import {
12 | addProjectToNxJsonInTree,
13 | names,
14 | offsetFromRoot,
15 | projectRootDir,
16 | ProjectType,
17 | toFileName,
18 | updateWorkspace,
19 | } from '@nrwl/workspace';
20 |
21 | import { snakeCase } from 'change-case';
22 |
23 | import { NxPythonSchematicSchema, NxPythonTemplate } from './schema';
24 | import {
25 | getBuildOptions,
26 | getLintOptions,
27 | getServeOptions,
28 | getTestOptions,
29 | } from './target-options';
30 |
31 | /**
32 | * Depending on your needs, you can change this to either `Library` or `Application`
33 | */
34 | //const projectType = ProjectType.Library;
35 | const projectType = ProjectType.Application;
36 |
37 | interface NormalizedSchema extends NxPythonSchematicSchema {
38 | projectName: string;
39 | snakeName: string;
40 | repoUrl: string;
41 | projectRoot: string;
42 | projectDirectory: string;
43 | projectDescription: string;
44 | parsedTags: string[];
45 | }
46 |
47 | function normalizeOptions(options: NxPythonSchematicSchema): NormalizedSchema {
48 | const name = toFileName(options.name);
49 | const snakeName = snakeCase(name);
50 | const projectDirectory = options.directory
51 | ? `${toFileName(options.directory)}/${name}`
52 | : name;
53 | const projectDescription = options.description;
54 | const repoUrl = options.repoUrl;
55 | const projectName = projectDirectory.replace(new RegExp('/', 'g'), '-');
56 | const projectRoot = `${projectRootDir(projectType)}/${projectDirectory}`;
57 | const parsedTags = options.tags
58 | ? options.tags.split(',').map((s) => s.trim())
59 | : [];
60 |
61 | return {
62 | ...options,
63 | projectName,
64 | snakeName,
65 | repoUrl,
66 | projectDescription,
67 | projectRoot,
68 | projectDirectory,
69 | parsedTags,
70 | };
71 | }
72 |
73 | function addFiles(options: NormalizedSchema): Rule {
74 | return mergeWith(
75 | apply(url(getTemplateFilesPath(options.template)), [
76 | applyTemplates({
77 | ...options,
78 | ...names(options.name),
79 | offsetFromRoot: offsetFromRoot(options.projectRoot),
80 | }),
81 | move(options.projectRoot),
82 | ])
83 | );
84 | }
85 |
86 | function getTemplateFilesPath(template: NxPythonTemplate) {
87 | if (template === 'django') {
88 | return `./files/django`;
89 | }
90 | if (template === 'flask') {
91 | return `./files/flask`;
92 | }
93 | return `./files/default`;
94 | }
95 |
96 | export default function (options: NxPythonSchematicSchema): Rule {
97 | const normalizedOptions = normalizeOptions(options);
98 | return chain([
99 | updateWorkspace((workspace) => {
100 | const appProjectRoot = normalizedOptions.projectRoot;
101 | const sourceRoot = `${appProjectRoot}/src`;
102 | const { projectName } = normalizedOptions;
103 | const name = names(projectName).propertyName;
104 | const project = workspace.projects.add({
105 | name: projectName,
106 | root: appProjectRoot,
107 | sourceRoot,
108 | projectType,
109 | });
110 |
111 | project.targets.add({
112 | name: 'build',
113 | builder: '@nx-python/nx-python:build',
114 | options: getBuildOptions(
115 | normalizedOptions.template,
116 | project,
117 | normalizedOptions
118 | ),
119 | });
120 |
121 | project.targets.add({
122 | name: 'serve',
123 | builder: '@nx-python/nx-python:serve',
124 | options: getServeOptions(normalizedOptions.template, project),
125 | });
126 |
127 | project.targets.add({
128 | name: 'test',
129 | builder: '@nx-python/nx-python:test',
130 | options: getTestOptions(normalizedOptions.template, project),
131 | });
132 |
133 | project.targets.add({
134 | name: 'lint',
135 | builder: '@nx-python/nx-python:lint',
136 | options: getLintOptions(normalizedOptions.template, project),
137 | });
138 | }),
139 | addProjectToNxJsonInTree(normalizedOptions.projectName, {
140 | tags: normalizedOptions.parsedTags,
141 | }),
142 | addFiles(normalizedOptions),
143 | ]);
144 | }
145 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🐍 NxPy: Nx Python plugin
2 |
3 | This project was generated using [Nx](https://nx.dev).
4 |
5 |
6 |
7 |
8 |
9 |
10 | The `nx-python` plugin allows users to create a basic python application using `nx` commands. To add the plugin to your project, just follow these steps:
11 |
12 | ## Getting started
13 |
14 | ### Create a Nx Workspace
15 |
16 | Before installing the `nx-python` plugin, it is required to have a pre-configured Nx Workspace . If you don't, then proceed to create a new one executing the following command:
17 |
18 | ```bash
19 | npx create-nx-workspace python-workspace --preset=empty --cli=nx --nx-cloud true
20 | cd python-workspace
21 | ```
22 |
23 | ### Install the `nx-python` plugin
24 |
25 | ```bash
26 | yarn add -D @nx-python/nx-python
27 | ```
28 |
29 | ### Adding an application to our workspace
30 |
31 | To create a new python application based on this plugin, please execute the following command:
32 |
33 | ```bash
34 | nx g @nx-python/nx-python:app
35 | ```
36 |
37 | **Note:** Replace `` with the name of your new application
38 |
39 | ### Advanced options
40 |
41 | * `--tags` or `-t` list of tags for project (used for linting)
42 | * `--description` Description of project
43 | * `--repoUrl` Repository URL
44 | * `--directory` or `-d` A directory where the project is placed
45 | * `--template` or `-f` python framework to use (f.ex `django` or `flask`, where `python` is used by default)
46 |
47 | #### Create Flask app
48 |
49 | ```bash
50 | nx g @nx-python/nx-python:app --template flask
51 | ```
52 |
53 | #### Create Django app
54 |
55 | ```bash
56 | nx g @nx-python/nx-python:app --template django
57 | ```
58 |
59 | ### Advanced configuration
60 |
61 | The plugin supports [cosmiconfig](https://www.npmjs.com/package/cosmiconfig) for global configuration.
62 |
63 | Simply add a `.nx-pythonrc` file to the root of your monorepo.
64 | Currently this configuration support specifying command options to be used
65 |
66 | ```json
67 | {
68 | "python": "python3",
69 | "commands": {
70 | "serve": "flask run",
71 | "lint": "-m pylint",
72 | "test": "-m pytest",
73 | }
74 | }
75 | ```
76 |
77 | See `src/utils/commands.ts` for command examples
78 |
79 | You can also specify project specific command overrides in `workspace.json` project entries or in `project.json` per project
80 |
81 | ```json
82 | "my-app": {
83 | "python": "python3",
84 | "commands": {
85 | "serve": "flask run",
86 | "lint": "-m pylint",
87 | "test": "-m unittest discover -s ./ -p",
88 | }
89 | }
90 | ```
91 |
92 | ## Usage
93 |
94 | After creating the `` application using the `nx-python` plugin. We can execute the build, lint, test and serve `nx commands` on this new application. Output will be stored on `dist//` directory.
95 |
96 | ### Building the app
97 |
98 | The `build` command is going to compile all the python files inside `` directory, using the `py_compile` native module.
99 |
100 | ```bash
101 | nx build
102 | ```
103 |
104 | More information here: [py_compile](https://docs.python.org/3/library/py_compile.html)
105 |
106 | ### Linting the application
107 |
108 | Unfortunately Python doesn't have a native linting module(yet!).
109 | It is required that you install the linting module beforehand.
110 |
111 | After you have installed the linting module you can perform the lint process with:
112 |
113 | ```bash
114 | nx lint
115 | ```
116 |
117 | ### Flake8
118 |
119 | `nx-python` uses the `Flake8` module by default to lint your application.
120 |
121 | More info here: [Flake8](https://flake8.pycqa.org/en/latest/)
122 |
123 | ```bash
124 | pip install Flake8
125 | ```
126 |
127 | ### Serving the application
128 |
129 | This is going to execute the main file in your python application.
130 |
131 | ```bash
132 | nx serve
133 | ```
134 |
135 | For flask and django, the main file is `manage.py`
136 |
137 | ### Testing your application
138 |
139 | The `test` command is going to execute all the test units inside your python app. You can add new test unit files.
140 |
141 | To test your python app, execute the command:
142 |
143 | ```bash
144 | nx test
145 | ```
146 |
147 | ### Unittest
148 |
149 | If you are using the default native `unittest` python module to for tests:
150 |
151 | * The filename must include the prefix `test`
152 |
153 | See more info here: [unittest](https://docs.python.org/3/library/unittest.html)
154 |
155 | ## Dependency Graph
156 |
157 | `packages/project-graph` includes some code which detects python projects and adds modified files in python projects to the dependency graph for the project.
158 |
159 | To detect a python project it must either:
160 |
161 | * have one or more python files (`.py` extension)
162 | * have `"compiler": "python"` set in project `build` options
163 |
164 | ## Contributing
165 |
166 | 🐍 All contributions are welcome. Make sure you follow the [code of conduct](CODE_OF_CONDUCT.md) in this repository.
167 |
168 | ## MIT License
169 |
170 | Made with 💜 by [Code ON](https://codeon.rocks) | [Melvin Vega](https://github.com/melveg) & [Diana Rodriguez](https://github.com/sponsors/alphacentauri82)
171 |
--------------------------------------------------------------------------------