1651954860
Comfy-table is designed as a library for building beautiful tables, while being easy to use.
470μs
or ~0.5ms
.~30μs
.i7-8700K
with a max single-core performance of 4.9GHz.cargo install cargo-criterion
and run cargo criterion
afterwards.Comfy-table is written for the current stable
Rust version. Older Rust versions may work but aren't officially supported.
use comfy_table::Table;
fn main() {
let mut table = Table::new();
table
.set_header(vec!["Header1", "Header2", "Header3"])
.add_row(vec![
"This is a text",
"This is another text",
"This is the third text",
])
.add_row(vec![
"This is another text",
"Now\nadd some\nmulti line stuff",
"This is awesome",
]);
println!("{table}");
}
Create a very basic table.
This table will become as wide as your content. Nothing fancy happening here.
+----------------------+----------------------+------------------------+
| Header1 | Header2 | Header3 |
+======================================================================+
| This is a text | This is another text | This is the third text |
|----------------------+----------------------+------------------------|
| This is another text | Now | This is awesome |
| | add some | |
| | multi line stuff | |
+----------------------+----------------------+------------------------+
use comfy_table::*;
use comfy_table::presets::UTF8_FULL;
use comfy_table::modifiers::UTF8_ROUND_CORNERS;
fn main() {
let mut table = Table::new();
table
.load_preset(UTF8_FULL)
.apply_modifier(UTF8_ROUND_CORNERS)
.set_content_arrangement(ContentArrangement::Dynamic)
.set_width(40)
.set_header(vec!["Header1", "Header2", "Header3"])
.add_row(vec![
Cell::new("Center aligned").set_alignment(CellAlignment::Center),
Cell::new("This is another text"),
Cell::new("This is the third text"),
])
.add_row(vec![
"This is another text",
"Now\nadd some\nmulti line stuff",
"This is awesome",
]);
// Set the default alignment for the third column to right
let column = table.column_mut(2).expect("Our table has three columns");
column.set_cell_alignment(CellAlignment::Right);
println!("{table}");
}
Create a table with UTF8 styling, and apply a modifier that gives the table round corners.
Additionally, the content will dynamically wrap to maintain a given table width.
If the table width isn't explicitely set and the program runs in a terminal, the terminal size will be used.
On top of this, we set the default alignment for the right column to Right
and the alignment of the left top cell to Center
.
╭────────────┬────────────┬────────────╮
│ Header1 ┆ Header2 ┆ Header3 │
╞════════════╪════════════╪════════════╡
│ This is a ┆ This is ┆ This is │
│ text ┆ another ┆ the third │
│ ┆ text ┆ text │
├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ This is ┆ Now ┆ This is │
│ another ┆ add some ┆ awesome │
│ text ┆ multi line ┆ │
│ ┆ stuff ┆ │
╰────────────┴────────────┴────────────╯
use comfy_table::*;
use comfy_table::presets::UTF8_FULL;
fn main() {
let mut table = Table::new();
table.load_preset(UTF8_FULL)
.set_content_arrangement(ContentArrangement::Dynamic)
.set_width(80)
.set_header(vec![
Cell::new("Header1").add_attribute(Attribute::Bold),
Cell::new("Header2").fg(Color::Green),
Cell::new("Header3"),
])
.add_row(vec![
Cell::new("This is a bold text").add_attribute(Attribute::Bold),
Cell::new("This is a green text").fg(Color::Green),
Cell::new("This one has black background").bg(Color::Black),
])
.add_row(vec![
Cell::new("Blinky boi").add_attribute(Attribute::SlowBlink),
Cell::new("This table's content is dynamically arranged. The table is exactly 80 characters wide.\nHere comes a reallylongwordthatshoulddynamicallywrap"),
Cell::new("COMBINE ALL THE THINGS")
.fg(Color::Green)
.bg(Color::Black)
.add_attributes(vec![
Attribute::Bold,
Attribute::SlowBlink,
])
]);
println!("{table}");
}
This code generates the table that can be seen at the top of this document.
A few examples can be found in the example
folder. To test an example, run cargo run --example $name
. E.g.:
cargo run --example readme_table
If you're looking for more information, take a look at the tests folder.
There are tests for almost every feature including a visual view for each resulting table.
Comfy-table is supposed to be minimalistic. A fixed set of features that just work for "normal" use-cases:
If you come up with an idea or an improvement that fits into the current scope of the project, feel free to create an issue :)!
Some things however will most likely not be added to the project since they drastically increase the complexity of the library or cover very specific edge-cases.
Such features are:
Comfy-table doesn't allow unsafe
code in its code-base. As it's a "simple" formatting library it also shouldn't be needed in the future.
However, Comfy-table uses two unsafe functions calls in its dependencies.
Both calls can be disabled by explicitely calling Table::force_no_tty.
Furthermore, all terminal related functionality, including styling, can be disabled by excluding the tty
feature flag. Without this flag no unsafe
code is used as far as I know.
crossterm::tty::IsTty
. This function is necessary to detect whether we're currently on a tty or not. This is only called if no explicit width is provided via Table::set_width
./// On unix the `isatty()` function returns true if a file
/// descriptor is a terminal.
#[cfg(unix)]
impl<S: AsRawFd> IsTty for S {
fn is_tty(&self) -> bool {
let fd = self.as_raw_fd();
unsafe { libc::isatty(fd) == 1 }
}
}
2. crossterm::terminal::size
. This function is necessary to detect the current terminal width if we're on a tty. This is only called if no explicit width is provided via Table::set_width
.
http://rosettacode.org/wiki/Terminal_control/Dimensions#Library:_BSD_libc This is another libc call which is used to communicate with /dev/tty
via a file descriptor.
...
if wrap_with_result(unsafe { ioctl(fd, TIOCGWINSZ.into(), &mut size) }).is_ok() {
Ok((size.ws_col, size.ws_row))
} else {
tput_size().ok_or_else(|| std::io::Error::last_os_error().into())
}
...
Download Details:
Author: nukesor
Source Code: https://github.com/nukesor/comfy-table
License: MIT license
1592298751
Do you want to build a superior beauty salon mobile app for your business? Then AppClues Infotech is a professional mobile app development company that works with a hair salon, Spa, and other businesses in the beauty industry.
Being the premier beauty salon mobile app development company we render quality solutions by making use of innovative thoughts. Our accomplished techies are adept at designing the feasible solutions that are affordable and cost-effective.
For more info:
Call: +1-978-309-9910
Email: info@appcluesinfotech.com
#how to build a mobile app for beauty salon #beauty salon app development company #best beauty salon app development company #top beauty salon app development company #create a beauty salon mobile app
1624653660
A useful tool several businesses implement for answering questions that potential customers may have is a chatbot. Many programming languages give web designers several ways on how to make a chatbot for their websites. They are capable of answering basic questions for visitors and offer innovation for businesses.
With the help of programming languages, it is possible to create a chatbot from the ground up to satisfy someone’s needs.
Before building a chatbot, it is ideal for web designers to determine how it will function on a website. Several chatbot duties center around fulfilling customers’ needs and questions or compiling and optimizing data via transactions.
Some benefits of implementing chatbots include:
Some programmers may choose to design a chatbox to function through predefined answers based on the questions customers may input or function by adapting and learning via human input.
#chatbots #latest news #the best way to build a chatbot in 2021 #build #build a chatbot #best way to build a chatbot
1595209620
As a developer, I have experienced changes in app when it is in production and the records have grown up to millions. In this specific case if you want to alter a column using simple migrations that will not work because of the following reasons:
It is not so easy if your production servers are under heavy load and the database tables have 100 million rows. Because such a migration will run for some seconds or even minutes and the database table can be locked for this time period – a no-go on a zero-downtime environment.
In this specific case you can use MySQL’s algorithms: Online DDL operations. That’s how you can do it in Laravel.
First of all create migration. For example I want to modify a column’s name the traditional migration will be:
Schema::table('users', function (Blueprint $table) {
$table->renameColumn('name', 'first_name');
});
Run the following command php artisan migrate –pretend this command will not run the migration rather it will print out it’s raw sql:
ALTER TABLE users CHANGE name first_name VARCHAR(191) NOT NULL
Copy that raw sql, remove following code:
Schema::table('users', function (Blueprint $table) {
$table->renameColumn('name', 'first_name');
});
Replace it with following in migrations up method:
\DB::statement('ALTER TABLE users CHANGE name first_name VARCHAR(191) NOT NULL');
Add desired algorithm, in my case query will look like this:
\DB::statement('ALTER TABLE users CHANGE name first_name VARCHAR(191) NOT NULL, ALGORITHM=INPLACE, LOCK=NONE;');
#laravel #mysql #php #alter heavy tables in production laravel #alter table in production laravel #alter tables with million of records in laravel #how to alter heavy table in production laravel #how to alter table in production larave #mysql online ddl operations
1571046022
Cryptocurrency is a decentralized digital currency that uses encryption techniques to regulate the generation of currency units and to verify the transfer of funds. Anonymity, decentralization, and security are among its main features. Cryptocurrency is not regulated or tracked by any centralized authority, government, or bank.
Blockchain, a decentralized peer-to-peer (P2P) network, which is comprised of data blocks, is an integral part of cryptocurrency. These blocks chronologically store information about transactions and adhere to a protocol for inter-node communication and validating new blocks. The data recorded in blocks cannot be altered without the alteration of all subsequent blocks.
In this article, we are going to explain how you can create a simple blockchain using the Python programming language.
Here is the basic blueprint of the Python class we’ll use for creating the blockchain:
class Block(object):
def __init__():
pass
#initial structure of the block class
def compute_hash():
pass
#producing the cryptographic hash of each block
class BlockChain(object):
def __init__(self):
#building the chain
def build_genesis(self):
pass
#creating the initial block
def build_block(self, proof_number, previous_hash):
pass
#builds new block and adds to the chain
@staticmethod
def confirm_validity(block, previous_block):
pass
#checks whether the blockchain is valid
def get_data(self, sender, receiver, amount):
pass
# declares data of transactions
@staticmethod
def proof_of_work(last_proof):
pass
#adds to the security of the blockchain
@property
def latest_block(self):
pass
#returns the last block in the chain
Now, let’s explain how the blockchain class works.
Here is the code for our initial block class:
import hashlib
import time
class Block(object):
def __init__(self, index, proof_number, previous_hash, data, timestamp=None):
self.index = index
self.proof_number = proof_number
self.previous_hash = previous_hash
self.data = data
self.timestamp = timestamp or time.time()
@property
def compute_hash(self):
string_block = "{}{}{}{}{}".format(self.index, self.proof_number, self.previous_hash, self.data, self.timestamp)
return hashlib.sha256(string_block.encode()).hexdigest()
As you can see above, the class constructor or initiation method ( init()) above takes the following parameters:
self
— just like any other Python class, this parameter is used to refer to the class itself. Any variable associated with the class can be accessed using it.
index
— it’s used to track the position of a block within the blockchain.
previous_hash
— it used to reference the hash of the previous block within the blockchain.
data—it
gives details of the transactions done, for example, the amount bought.
timestamp—it
inserts a timestamp for all the transactions performed.
The second method in the class, compute_hash , is used to produce the cryptographic hash of each block based on the above values.
As you can see, we imported the SHA-256 algorithm into the cryptocurrency blockchain project to help in getting the hashes of the blocks.
Once the values have been placed inside the hashing module, the algorithm will return a 256-bit string denoting the contents of the block.
So, this is what gives the blockchain immutability. Since each block will be represented by a hash, which will be computed from the hash of the previous block, corrupting any block in the chain will make the other blocks have invalid hashes, resulting in breakage of the whole blockchain network.
The whole concept of a blockchain is based on the fact that the blocks are “chained” to each other. Now, we’ll create a blockchain class that will play the critical role of managing the entire chain.
It will keep the transactions data and include other helper methods for completing various roles, such as adding new blocks.
Let’s talk about the helper methods.
Here is the code:
class BlockChain(object):
def __init__(self):
self.chain = []
self.current_data = []
self.nodes = set()
self.build_genesis()
The init() constructor method is what instantiates the blockchain.
Here are the roles of its attributes:
self.chain — this variable stores all the blocks.
self.current_data — this variable stores information about the transactions in the block.
self.build_genesis() — this method is used to create the initial block in the chain.
The build_genesis()
method is used for creating the initial block in the chain, that is, a block without any predecessors. The genesis block is what represents the beginning of the blockchain.
To create it, we’ll call the build_block()
method and give it some default values. The parameters proof_number
and previous_hash
are both given a value of zero, though you can give them any value you desire.
Here is the code:
def build_genesis(self):
self.build_block(proof_number=0, previous_hash=0)
def build_block(self, proof_number, previous_hash):
block = Block(
index=len(self.chain),
proof_number=proof_number,
previous_hash=previous_hash,
data=self.current_data
)
self.current_data = []
self.chain.append(block)
return block
The confirm_validity
method is critical in examining the integrity of the blockchain and making sure inconsistencies are lacking.
As explained earlier, hashes are pivotal for realizing the security of the cryptocurrency blockchain, because any slight alteration in an object will result in the creation of an entirely different hash.
Thus, the confirm_validity
method utilizes a series of if statements to assess whether the hash of each block has been compromised.
Furthermore, it also compares the hash values of every two successive blocks to identify any anomalies. If the chain is working properly, it returns true; otherwise, it returns false.
Here is the code:
def confirm_validity(block, previous_block):
if previous_block.index + 1 != block.index:
return False
elif previous_block.compute_hash != block.previous_hash:
return False
elif block.timestamp <= previous_block.timestamp:
return False
return True
The get_data
method is important in declaring the data of transactions on a block. This method takes three parameters (sender’s information, receiver’s information, and amount) and adds the transaction data to the self.current_data list.
Here is the code:
def get_data(self, sender, receiver, amount):
self.current_data.append({
'sender': sender,
'receiver': receiver,
'amount': amount
})
return True
In blockchain technology, Proof of Work (PoW) refers to the complexity involved in mining or generating new blocks on the blockchain.
For example, the PoW can be implemented by identifying a number that solves a problem whenever a user completes some computing work. Anyone on the blockchain network should find the number complex to identify but easy to verify — this is the main concept of PoW.
This way, it discourages spamming and compromising the integrity of the network.
In this article, we’ll illustrate how to include a Proof of Work algorithm in a blockchain cryptocurrency project.
Finally, the latest_block() helper method is used for retrieving the last block on the network, which is actually the current block.
Here is the code:
def latest_block(self):
return self.chain[-1]
Now, this is the most exciting section!
Initially, the transactions are kept in a list of unverified transactions. Mining refers to the process of placing the unverified transactions in a block and solving the PoW problem. It can be referred to as the computing work involved in verifying the transactions.
If everything has been figured out correctly, a block is created or mined and joined together with the others in the blockchain. If users have successfully mined a block, they are often rewarded for using their computing resources to solve the PoW problem.
Here is the mining method in this simple cryptocurrency blockchain project:
def block_mining(self, details_miner):
self.get_data(
sender="0", #it implies that this node has created a new block
receiver=details_miner,
quantity=1, #creating a new block (or identifying the proof number) is awarded with 1
)
last_block = self.latest_block
last_proof_number = last_block.proof_number
proof_number = self.proof_of_work(last_proof_number)
last_hash = last_block.compute_hash
block = self.build_block(proof_number, last_hash)
return vars(block)
Here is the whole code for our crypto blockchain class in Python:
import hashlib
import time
class Block(object):
def __init__(self, index, proof_number, previous_hash, data, timestamp=None):
self.index = index
self.proof_number = proof_number
self.previous_hash = previous_hash
self.data = data
self.timestamp = timestamp or time.time()
@property
def compute_hash(self):
string_block = "{}{}{}{}{}".format(self.index, self.proof_number, self.previous_hash, self.data, self.timestamp)
return hashlib.sha256(string_block.encode()).hexdigest()
def __repr__(self):
return "{} - {} - {} - {} - {}".format(self.index, self.proof_number, self.previous_hash, self.data, self.timestamp)
class BlockChain(object):
def __init__(self):
self.chain = []
self.current_data = []
self.nodes = set()
self.build_genesis()
def build_genesis(self):
self.build_block(proof_number=0, previous_hash=0)
def build_block(self, proof_number, previous_hash):
block = Block(
index=len(self.chain),
proof_number=proof_number,
previous_hash=previous_hash,
data=self.current_data
)
self.current_data = []
self.chain.append(block)
return block
@staticmethod
def confirm_validity(block, previous_block):
if previous_block.index + 1 != block.index:
return False
elif previous_block.compute_hash != block.previous_hash:
return False
elif block.timestamp <= previous_block.timestamp:
return False
return True
def get_data(self, sender, receiver, amount):
self.current_data.append({
'sender': sender,
'receiver': receiver,
'amount': amount
})
return True
@staticmethod
def proof_of_work(last_proof):
pass
@property
def latest_block(self):
return self.chain[-1]
def chain_validity(self):
pass
def block_mining(self, details_miner):
self.get_data(
sender="0", #it implies that this node has created a new block
receiver=details_miner,
quantity=1, #creating a new block (or identifying the proof number) is awared with 1
)
last_block = self.latest_block
last_proof_number = last_block.proof_number
proof_number = self.proof_of_work(last_proof_number)
last_hash = last_block.compute_hash
block = self.build_block(proof_number, last_hash)
return vars(block)
def create_node(self, address):
self.nodes.add(address)
return True
@staticmethod
def get_block_object(block_data):
return Block(
block_data['index'],
block_data['proof_number'],
block_data['previous_hash'],
block_data['data'],
timestamp=block_data['timestamp']
)
blockchain = BlockChain()
print("GET READY MINING ABOUT TO START")
print(blockchain.chain)
last_block = blockchain.latest_block
last_proof_number = last_block.proof_number
proof_number = blockchain.proof_of_work(last_proof_number)
blockchain.get_data(
sender="0", #this means that this node has constructed another block
receiver="LiveEdu.tv",
amount=1, #building a new block (or figuring out the proof number) is awarded with 1
)
last_hash = last_block.compute_hash
block = blockchain.build_block(proof_number, last_hash)
print("WOW, MINING HAS BEEN SUCCESSFUL!")
print(blockchain.chain)
Now, let’s try to run our code to see if we can generate some digital coins…
Wow, it worked!
That is it!
We hope that this article has assisted you to understand the underlying technology that powers cryptocurrencies such as Bitcoin and Ethereum.
We just illustrated the basic ideas for making your feet wet in the innovative blockchain technology. The project above can still be enhanced by incorporating other features to make it more useful and robust.
Thanks for reading !
Do you have any comments or questions? Please share them below.
#python #cryptocurrency
1651954860
Comfy-table is designed as a library for building beautiful tables, while being easy to use.
470μs
or ~0.5ms
.~30μs
.i7-8700K
with a max single-core performance of 4.9GHz.cargo install cargo-criterion
and run cargo criterion
afterwards.Comfy-table is written for the current stable
Rust version. Older Rust versions may work but aren't officially supported.
use comfy_table::Table;
fn main() {
let mut table = Table::new();
table
.set_header(vec!["Header1", "Header2", "Header3"])
.add_row(vec![
"This is a text",
"This is another text",
"This is the third text",
])
.add_row(vec![
"This is another text",
"Now\nadd some\nmulti line stuff",
"This is awesome",
]);
println!("{table}");
}
Create a very basic table.
This table will become as wide as your content. Nothing fancy happening here.
+----------------------+----------------------+------------------------+
| Header1 | Header2 | Header3 |
+======================================================================+
| This is a text | This is another text | This is the third text |
|----------------------+----------------------+------------------------|
| This is another text | Now | This is awesome |
| | add some | |
| | multi line stuff | |
+----------------------+----------------------+------------------------+
use comfy_table::*;
use comfy_table::presets::UTF8_FULL;
use comfy_table::modifiers::UTF8_ROUND_CORNERS;
fn main() {
let mut table = Table::new();
table
.load_preset(UTF8_FULL)
.apply_modifier(UTF8_ROUND_CORNERS)
.set_content_arrangement(ContentArrangement::Dynamic)
.set_width(40)
.set_header(vec!["Header1", "Header2", "Header3"])
.add_row(vec![
Cell::new("Center aligned").set_alignment(CellAlignment::Center),
Cell::new("This is another text"),
Cell::new("This is the third text"),
])
.add_row(vec![
"This is another text",
"Now\nadd some\nmulti line stuff",
"This is awesome",
]);
// Set the default alignment for the third column to right
let column = table.column_mut(2).expect("Our table has three columns");
column.set_cell_alignment(CellAlignment::Right);
println!("{table}");
}
Create a table with UTF8 styling, and apply a modifier that gives the table round corners.
Additionally, the content will dynamically wrap to maintain a given table width.
If the table width isn't explicitely set and the program runs in a terminal, the terminal size will be used.
On top of this, we set the default alignment for the right column to Right
and the alignment of the left top cell to Center
.
╭────────────┬────────────┬────────────╮
│ Header1 ┆ Header2 ┆ Header3 │
╞════════════╪════════════╪════════════╡
│ This is a ┆ This is ┆ This is │
│ text ┆ another ┆ the third │
│ ┆ text ┆ text │
├╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ This is ┆ Now ┆ This is │
│ another ┆ add some ┆ awesome │
│ text ┆ multi line ┆ │
│ ┆ stuff ┆ │
╰────────────┴────────────┴────────────╯
use comfy_table::*;
use comfy_table::presets::UTF8_FULL;
fn main() {
let mut table = Table::new();
table.load_preset(UTF8_FULL)
.set_content_arrangement(ContentArrangement::Dynamic)
.set_width(80)
.set_header(vec![
Cell::new("Header1").add_attribute(Attribute::Bold),
Cell::new("Header2").fg(Color::Green),
Cell::new("Header3"),
])
.add_row(vec![
Cell::new("This is a bold text").add_attribute(Attribute::Bold),
Cell::new("This is a green text").fg(Color::Green),
Cell::new("This one has black background").bg(Color::Black),
])
.add_row(vec![
Cell::new("Blinky boi").add_attribute(Attribute::SlowBlink),
Cell::new("This table's content is dynamically arranged. The table is exactly 80 characters wide.\nHere comes a reallylongwordthatshoulddynamicallywrap"),
Cell::new("COMBINE ALL THE THINGS")
.fg(Color::Green)
.bg(Color::Black)
.add_attributes(vec![
Attribute::Bold,
Attribute::SlowBlink,
])
]);
println!("{table}");
}
This code generates the table that can be seen at the top of this document.
A few examples can be found in the example
folder. To test an example, run cargo run --example $name
. E.g.:
cargo run --example readme_table
If you're looking for more information, take a look at the tests folder.
There are tests for almost every feature including a visual view for each resulting table.
Comfy-table is supposed to be minimalistic. A fixed set of features that just work for "normal" use-cases:
If you come up with an idea or an improvement that fits into the current scope of the project, feel free to create an issue :)!
Some things however will most likely not be added to the project since they drastically increase the complexity of the library or cover very specific edge-cases.
Such features are:
Comfy-table doesn't allow unsafe
code in its code-base. As it's a "simple" formatting library it also shouldn't be needed in the future.
However, Comfy-table uses two unsafe functions calls in its dependencies.
Both calls can be disabled by explicitely calling Table::force_no_tty.
Furthermore, all terminal related functionality, including styling, can be disabled by excluding the tty
feature flag. Without this flag no unsafe
code is used as far as I know.
crossterm::tty::IsTty
. This function is necessary to detect whether we're currently on a tty or not. This is only called if no explicit width is provided via Table::set_width
./// On unix the `isatty()` function returns true if a file
/// descriptor is a terminal.
#[cfg(unix)]
impl<S: AsRawFd> IsTty for S {
fn is_tty(&self) -> bool {
let fd = self.as_raw_fd();
unsafe { libc::isatty(fd) == 1 }
}
}
2. crossterm::terminal::size
. This function is necessary to detect the current terminal width if we're on a tty. This is only called if no explicit width is provided via Table::set_width
.
http://rosettacode.org/wiki/Terminal_control/Dimensions#Library:_BSD_libc This is another libc call which is used to communicate with /dev/tty
via a file descriptor.
...
if wrap_with_result(unsafe { ioctl(fd, TIOCGWINSZ.into(), &mut size) }).is_ok() {
Ok((size.ws_col, size.ws_row))
} else {
tput_size().ok_or_else(|| std::io::Error::last_os_error().into())
}
...
Download Details:
Author: nukesor
Source Code: https://github.com/nukesor/comfy-table
License: MIT license