{"id":16543237,"url":"https://github.com/codemation/jawf","last_synced_at":"2025-03-04T07:14:09.150Z","repository":{"id":62572188,"uuid":"195769733","full_name":"codemation/Jawf","owner":"codemation","description":"Just Another Web Framework - streamlining flask application development","archived":false,"fork":false,"pushed_at":"2019-11-11T00:13:01.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-14T11:16:46.628Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/codemation.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-07-08T08:31:08.000Z","updated_at":"2019-11-11T00:13:03.000Z","dependencies_parsed_at":"2022-11-03T18:26:45.730Z","dependency_job_id":null,"html_url":"https://github.com/codemation/Jawf","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemation%2FJawf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemation%2FJawf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemation%2FJawf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/codemation%2FJawf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/codemation","download_url":"https://codeload.github.com/codemation/Jawf/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241801257,"owners_count":20022390,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T18:59:43.462Z","updated_at":"2025-03-04T07:14:09.131Z","avatar_url":"https://github.com/codemation.png","language":"Python","readme":"# Jawf\nJust Another Web Framework - streamlining flask application development\n\n## Basic Usage\n\n### Initialize a JAWF Project directory\n    \n    $ jawf --init \u003cprojName\u003e \n\n    $ jawf --init Project1\n\n    Not inside existing jawf project\n    Succesfully created jawf project: Project1\n\n### Add an app to project\n\n    Usage: jawf --add-app \u003capp-name\u003e [--route \u003curlpattern\u003e default: /app-name]\n    $ jawf --add-app myfirstapp\n    $ jawf --add-app homepage --route /\n\n    $ jawf --add-app myfirstapp\n    Not inside existing jawf project\n    --add-app\n    must be used within an existing project directory\n    or combined with --project \u003cproject-path\u003e \n\n    $ cd Project1/\n    /Project1 $ jawf --add-app myfirstapp\n    Detected Existing project:Project1\n    app myfirstapp was created successfully within /home/josh/python/mysql/Project1/\n\nThis creates an application which is immedietly wired up to the project. Can be tested right away. \n\n    /Project1$ python3 server.py \n    * Serving Flask app \"server\" (lazy loading)\n    * Environment: production\n    WARNING: This is a development server. Do not use it in a production deployment.\n    Use a production WSGI server instead.\n    * Debug mode: on\n    * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)\n    * Restarting with stat\n    * Debugger is active!\n    * Debugger PIN: 144-714-176\n\n    $ curl http://0.0.0.0:8080/myfirstapp\n    \u003ch1\u003eHello myfirstapp World\u003c/h1\u003e\n\nA closer look at the skeleton of the application created.\n\n    Project1/apps/myfirstapp/myfirstapp.py\n\n    # myfirstapp\n    def run(server):\n        # Add import libraries here, run only once, when server is started\n        @server.route('/myfirstapp')\n        def myfirstapp_func():\n            # Add repeatable logic here, run as often as endpoint is called.\n            print(\"Hello myfirstapp World\") \n            return \"\u003ch1\u003eHello myfirstapp World\u003c/h1\u003e\", 200\n\nIf you are familiar with flask routing, this is exactly the same. The work of wiring together multiple endpoints to a primary server app is done for you.    \n### Add an DB to project\n\nJAWF makes it easy to add new databaes, tables to a project as well as accessing the data in combination with [pyql]\u003chttps://github.com/codemation/pyql\u003e\n\n#### Supported database types: sqlite3, mysql\n\n    jawf --add-db \u003cdb-name\u003e [--type mysql default: sqlite3]\n    jawf --add-db finance --type mysql\n    jawf --add-db stocks \n\nsqlite3 is a builtin library with python3 and creates light-weight databases in place for storing / retreiving data. \n\n#### sqlite3\n\n    Project1$ jawf --add-db stocks\n    Detected Existing project:Project1\n    db stocks created successfully\n\nThis does not immedietly create a database until a table is added, and server is started.\n\n##### Lets have a look at the DB file created at Project1/dbs/stocks/\n\n    stocks_db.py\n\n    # stocks - type sqlite3\n    def run(server):\n        import sys, os\n        @server.route('/stocks_attach')\n        def stocks_attach():\n            config=dict()\n                \n            with open('.cmddir', 'r') as projDir:\n                for projectPath in projDir:\n                    config['database'] = f'{projectPath}dbs/stocks/stocks'\n            #USE ENV PATH for PYQL library or /pyql/\n            sys.path.append('/pyql/' if os.getenv('PYQL_PATH') == None else os.getenv('PYQL_PATH'))\n            try:\n                import data, sqlite3\n                from . import setup\n                server.data['stocks'] = data.database(sqlite3.connect, **config)\n                setup.attach_tables(server)\n                return {\"status\": 200, \"message\": \"stocks attached successfully\"}, 200\n            except Exception as e:\n                return {\"status\": 200, \"message\": repr(e)}, 500\n        stocks_attach()\n\n##### Whats happening here:\nSimilar to app's there is an endpoint created to allow app developers control on when the web-server will attempt to access the DB\nThis becomes more useful with remote-db's or in micro-service deployments, when a DB server may not be ready as soon as the APP server. \n\n    # stocks - type sqlite3\n    def run(server):\n        import sys, os\n        @server.route('/stocks_attach')\n        def stocks_attach():\n            config=dict()\n\nHere we are first checking the project relative directory, as this is important wth sqlite3 databases which are always locally existing within the server.\nBy default, mysqlite Db will exist within dbs/db-name/db\n\n            with open('.cmddir', 'r') as projDir:\n                for projectPath in projDir:\n                    config['database'] = f'{projectPath}dbs/stocks/stocks'\n\nPYQL is a dependency. If not directly install int a venv, this can be accessed using a ENV Variable PYQL_PATH or default /pyql/ system path.\n\n            #USE ENV PATH for PYQL library or /pyql/\n            sys.path.append('/pyql/' if os.getenv('PYQL_PATH') == None else os.getenv('PYQL_PATH'))\n\nFinally PYQL libraryies are imported, and DB connector is attached to the server object (available in all JAWF apps), then tables are attached, and configured if not existing.\n\n            try:\n                import data, sqlite3\n                from . import setup\n                server.data['stocks'] = data.database(sqlite3.connect, **config)\n                setup.attach_tables(server)\n                return {\"status\": 200, \"message\": \"stocks attached successfully\"}, 200\n            except Exception as e:\n                return {\"status\": 200, \"message\": repr(e)}, 500\n\n\n#### mysql\n\n    Project1$$ jawf --add-db trades --type mysql\n    Detected Existing project:Project1\n    db trades created successfully \n\nDatabases must be created already within the mysql instance, as well as appropiate user / permissions for accessing the DB, creating tables.\n\n    trades.py\n\n    # trades - type mysql\n    def run(server):\n        import sys, os\n        @server.route('/trades_attach')\n        def trades_attach():\n            config=dict()\n                \n            env = ['DB_USER','DB_PASSWORD','DB_HOST', 'DB_PORT']\n            conf = ['user','password','database','host','port']\n            try:\n                config = {cnfVal: os.getenv(dbVal).rstrip() for dbVal,cnfVal in zip(env,conf)}\n            except Exception as e:\n                print('Missing an environment variable')\n                config= {cnfVal: os.getenv(dbVal) for dbVal,cnfVal in zip(env,conf)}\n                print(config)\n                return {\n                    \"status\": 500, \n                    \"message\": \"Missing environment variable(s)\",\n                    \"env-vars\": config\n                }, 500 \n            #USE ENV PATH for PYQL library or /pyql/\n            sys.path.append('/pyql/' if os.getenv('PYQL_PATH') == None else os.getenv('PYQL_PATH'))\n            try:\n                import data, mysql\n                from . import setup\n                server.data['trades'] = data.database(mysql.connector.connect, **config)\n                setup.attach_tables(server)\n                return {\"status\": 200, \"message\": \"trades attached successfully\"}, 200\n            except Exception as e:\n                return {\"status\": 200, \"message\": repr(e)}, 500\n        trades_attach()\n\nMuch of the same logic is shared with SQLITE3 databases, but the most important different is the DB connector requirements. As this is not always a DB locally existing(it could be), we need to know a few more details on how to access the database.\n\nHere we are looking for 4 different ENV vars. These can be set in a number of different ways or passed into the /DB_NAME_attach endpoint via a POST request, passing in a JSON key-value pair for 'user','password','database','host','port'\n\n            env = ['DB_USER','DB_PASSWORD','DB_HOST', 'DB_PORT', DB_NAME]\n            conf = ['user','password','host','port', database]\n            try:\n                config = {cnfVal: os.getenv(dbVal).rstrip() for dbVal,cnfVal in zip(env,conf)}\n            except Exception as e:\n                print('Missing an environment variable')\n                config= {cnfVal: os.getenv(dbVal) for dbVal,cnfVal in zip(env,conf)}\n                print(config)\n                return {\n                    \"status\": 500, \n                    \"message\": \"Missing environment variable(s)\",\n                    \"env-vars\": config\n                }, 500 \n\n#### Add a Table to a DB\nDatabases are comprised of tables, so we need to configure the schema for each of the tables we want the JAWF project to create. PYQL will automatically discover tables which already exist and be made accessible via the server.data['databaseName'].tables['tableName']\n\n    jawf --add-db-table \u003cdb-name\u003e --table \u003ctable-name\u003e\n    jawf --add-db-table finance --table purchaseOrders\n\n    $ jawf --add-db-table trades --table daytrades\n    Detected Existing project:Project1\n    table daytrades config created within db trades\n\nThis creates a daytrades table within the tables dir of the trades database. \n\n    def db_attach(server):\n        db = server.data['trades']\n        # Example \n        # db.create_table(\n        #    'users', # table-name\n        #     [\n        #        ('userid', int, 'AUTOINCREMENT'),\n        #        ('username', str, 'UNIQUE NOT NULL'),\n        #        ('email', str, 'NOT NULL'),\n        #        ('join_date', str),\n        #        ('last_login', str),\n        #     ],\n        # 'userid' # Primary Key\n        # )\n        #UNCOMMENT Below to create\n        #\n        #db.create_table(\n        #    'daytrades', [\n        #        (), \n        #        (), \n        #        ()\n        #)\n        pass # Enter db.create_table statement here\n\nSee PYQL docs for more information Table SCHEMA usage, but the above template gets you started. ","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodemation%2Fjawf","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodemation%2Fjawf","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodemation%2Fjawf/lists"}